gosu 0.13.3 → 0.14.0.pre2
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.
- checksums.yaml +4 -4
- data/Gosu/Audio.hpp +15 -11
- data/Gosu/Font.hpp +24 -20
- data/Gosu/Fwd.hpp +1 -1
- data/Gosu/Graphics.hpp +8 -9
- data/Gosu/ImageData.hpp +1 -1
- data/Gosu/Input.hpp +1 -1
- data/Gosu/Math.hpp +0 -18
- data/Gosu/Text.hpp +22 -30
- data/Gosu/TextInput.hpp +13 -0
- data/Gosu/Utility.hpp +2 -0
- data/Gosu/Window.hpp +3 -3
- data/README.md +3 -4
- data/ext/gosu/extconf.rb +7 -9
- data/lib/gosu/swig_patches.rb +1 -4
- data/rdoc/gosu.rb +34 -9
- data/src/Audio.cpp +6 -6
- data/src/AudioImpl.cpp +2 -2
- data/src/Bitmap.cpp +1 -2
- data/src/BitmapIO.cpp +21 -2
- data/src/BlockAllocator.cpp +1 -1
- data/src/Channel.cpp +7 -1
- data/src/ClipRectStack.hpp +4 -1
- data/src/Color.cpp +2 -1
- data/src/DirectoriesWin.cpp +1 -1
- data/src/DrawOp.hpp +8 -4
- data/src/DrawOpQueue.hpp +13 -24
- data/src/FileUnix.cpp +3 -1
- data/src/Font.cpp +92 -96
- data/src/GosuGLView.cpp +59 -31
- data/src/GosuGLView.hpp +14 -0
- data/src/GosuViewController.cpp +21 -21
- data/src/{GosuViewController.h → GosuViewController.hpp} +2 -4
- data/src/Graphics.cpp +71 -38
- data/src/GraphicsImpl.hpp +12 -29
- data/src/Image.cpp +5 -7
- data/src/Input.cpp +7 -5
- data/src/InputUIKit.cpp +19 -37
- data/src/Macro.cpp +10 -2
- data/src/MarkupParser.cpp +241 -0
- data/src/MarkupParser.hpp +61 -0
- data/src/Math.cpp +1 -1
- data/src/OffScreenTarget.cpp +99 -0
- data/src/OffScreenTarget.hpp +23 -0
- data/src/OggFile.hpp +10 -0
- data/src/RenderState.hpp +0 -2
- data/src/Resolution.cpp +2 -2
- data/src/RubyGosu.cxx +457 -244
- data/src/TexChunk.cpp +8 -6
- data/src/Text.cpp +58 -345
- data/src/TextBuilder.cpp +138 -0
- data/src/TextBuilder.hpp +55 -0
- data/src/TextInput.cpp +27 -10
- data/src/Texture.cpp +22 -17
- data/src/Texture.hpp +19 -20
- data/src/TimingApple.cpp +5 -7
- data/src/TimingUnix.cpp +1 -4
- data/src/TimingWin.cpp +4 -1
- data/src/TrueTypeFont.cpp +282 -0
- data/src/TrueTypeFont.hpp +66 -0
- data/src/TrueTypeFontApple.cpp +65 -0
- data/src/TrueTypeFontUnix.cpp +91 -0
- data/src/TrueTypeFontWin.cpp +82 -0
- data/src/Utility.cpp +40 -0
- data/src/Window.cpp +7 -6
- data/src/WindowUIKit.cpp +9 -4
- data/src/stb_truetype.h +4589 -0
- data/src/utf8proc.c +755 -0
- data/src/utf8proc.h +699 -0
- data/src/utf8proc_data.h +14386 -0
- metadata +23 -16
- data/src/FormattedString.cpp +0 -237
- data/src/FormattedString.hpp +0 -47
- data/src/GosuAppDelegate.cpp +0 -30
- data/src/GosuAppDelegate.h +0 -8
- data/src/GosuGLView.h +0 -8
- data/src/TextApple.cpp +0 -212
- data/src/TextTTFWin.cpp +0 -197
- data/src/TextUnix.cpp +0 -280
- data/src/TextWin.cpp +0 -191
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gosu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0.pre2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julian Raschke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
2D game development library.
|
@@ -81,14 +81,10 @@ files:
|
|
81
81
|
- src/FileUnix.cpp
|
82
82
|
- src/FileWin.cpp
|
83
83
|
- src/Font.cpp
|
84
|
-
- src/FormattedString.cpp
|
85
|
-
- src/FormattedString.hpp
|
86
|
-
- src/GosuAppDelegate.cpp
|
87
|
-
- src/GosuAppDelegate.h
|
88
84
|
- src/GosuGLView.cpp
|
89
|
-
- src/GosuGLView.
|
85
|
+
- src/GosuGLView.hpp
|
90
86
|
- src/GosuViewController.cpp
|
91
|
-
- src/GosuViewController.
|
87
|
+
- src/GosuViewController.hpp
|
92
88
|
- src/Graphics.cpp
|
93
89
|
- src/GraphicsImpl.hpp
|
94
90
|
- src/IO.cpp
|
@@ -102,7 +98,11 @@ files:
|
|
102
98
|
- src/MPEGFile.hpp
|
103
99
|
- src/Macro.cpp
|
104
100
|
- src/Macro.hpp
|
101
|
+
- src/MarkupParser.cpp
|
102
|
+
- src/MarkupParser.hpp
|
105
103
|
- src/Math.cpp
|
104
|
+
- src/OffScreenTarget.cpp
|
105
|
+
- src/OffScreenTarget.hpp
|
106
106
|
- src/OggFile.hpp
|
107
107
|
- src/RenderState.hpp
|
108
108
|
- src/Resolution.cpp
|
@@ -113,11 +113,9 @@ files:
|
|
113
113
|
- src/TexChunk.cpp
|
114
114
|
- src/TexChunk.hpp
|
115
115
|
- src/Text.cpp
|
116
|
-
- src/
|
116
|
+
- src/TextBuilder.cpp
|
117
|
+
- src/TextBuilder.hpp
|
117
118
|
- src/TextInput.cpp
|
118
|
-
- src/TextTTFWin.cpp
|
119
|
-
- src/TextUnix.cpp
|
120
|
-
- src/TextWin.cpp
|
121
119
|
- src/Texture.cpp
|
122
120
|
- src/Texture.hpp
|
123
121
|
- src/TimingApple.cpp
|
@@ -125,6 +123,11 @@ files:
|
|
125
123
|
- src/TimingWin.cpp
|
126
124
|
- src/Transform.cpp
|
127
125
|
- src/TransformStack.hpp
|
126
|
+
- src/TrueTypeFont.cpp
|
127
|
+
- src/TrueTypeFont.hpp
|
128
|
+
- src/TrueTypeFontApple.cpp
|
129
|
+
- src/TrueTypeFontUnix.cpp
|
130
|
+
- src/TrueTypeFontWin.cpp
|
128
131
|
- src/Utility.cpp
|
129
132
|
- src/UtilityApple.cpp
|
130
133
|
- src/UtilityWin.cpp
|
@@ -136,7 +139,11 @@ files:
|
|
136
139
|
- src/WindowUIKit.cpp
|
137
140
|
- src/stb_image.h
|
138
141
|
- src/stb_image_write.h
|
142
|
+
- src/stb_truetype.h
|
139
143
|
- src/stb_vorbis.c
|
144
|
+
- src/utf8proc.c
|
145
|
+
- src/utf8proc.h
|
146
|
+
- src/utf8proc_data.h
|
140
147
|
homepage: https://www.libgosu.org/
|
141
148
|
licenses:
|
142
149
|
- MIT
|
@@ -153,15 +160,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
160
|
requirements:
|
154
161
|
- - ">="
|
155
162
|
- !ruby/object:Gem::Version
|
156
|
-
version: 1.
|
163
|
+
version: 1.9.3
|
157
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
165
|
requirements:
|
159
|
-
- - "
|
166
|
+
- - ">"
|
160
167
|
- !ruby/object:Gem::Version
|
161
|
-
version:
|
168
|
+
version: 1.3.1
|
162
169
|
requirements: []
|
163
170
|
rubyforge_project:
|
164
|
-
rubygems_version: 2.7.
|
171
|
+
rubygems_version: 2.7.6
|
165
172
|
signing_key:
|
166
173
|
specification_version: 4
|
167
174
|
summary: 2D game development library.
|
data/src/FormattedString.cpp
DELETED
@@ -1,237 +0,0 @@
|
|
1
|
-
#include "FormattedString.hpp"
|
2
|
-
#include <Gosu/Utility.hpp>
|
3
|
-
#include <cwchar>
|
4
|
-
#include <cwctype>
|
5
|
-
using namespace std;
|
6
|
-
|
7
|
-
static unsigned flags(int b, int u, int i)
|
8
|
-
{
|
9
|
-
unsigned flags = 0;
|
10
|
-
if (b > 0) flags |= Gosu::FF_BOLD;
|
11
|
-
if (u > 0) flags |= Gosu::FF_UNDERLINE;
|
12
|
-
if (i > 0) flags |= Gosu::FF_ITALIC;
|
13
|
-
return flags;
|
14
|
-
}
|
15
|
-
|
16
|
-
bool Gosu::FormattedString::FormattedChar::same_style_as(const FormattedChar& other) const
|
17
|
-
{
|
18
|
-
return wc && other.wc && color == other.color && flags == other.flags;
|
19
|
-
}
|
20
|
-
|
21
|
-
Gosu::FormattedString::FormattedString()
|
22
|
-
{
|
23
|
-
}
|
24
|
-
|
25
|
-
Gosu::FormattedString::FormattedString(const wchar_t* html, unsigned base_flags)
|
26
|
-
{
|
27
|
-
// Remove \r characters if existent. Avoid a copy if we don't need one.
|
28
|
-
wstring unixified;
|
29
|
-
// We have to explicitly qualify wcschr to avoid an ambiguity on macOS.
|
30
|
-
if (std::wcschr(html, L'\r')) {
|
31
|
-
unixified.resize(wcslen(html));
|
32
|
-
unsigned pos = 0;
|
33
|
-
while (*html) {
|
34
|
-
if (*html != '\r') {
|
35
|
-
unixified[pos++] = *html;
|
36
|
-
}
|
37
|
-
++html;
|
38
|
-
}
|
39
|
-
unixified.resize(pos);
|
40
|
-
html = unixified.c_str();
|
41
|
-
}
|
42
|
-
|
43
|
-
size_t len = wcslen(html);
|
44
|
-
|
45
|
-
// Just skip all this if there are entities or formatting tags in the string.
|
46
|
-
if (wcscspn(html, L"<&") == len) {
|
47
|
-
simple_string = html;
|
48
|
-
simple_flags = base_flags;
|
49
|
-
return;
|
50
|
-
}
|
51
|
-
|
52
|
-
unsigned pos = 0;
|
53
|
-
int b = (base_flags & FF_BOLD) ? 1 : 0,
|
54
|
-
u = (base_flags & FF_UNDERLINE) ? 1 : 0,
|
55
|
-
i = (base_flags & FF_ITALIC) ? 1 : 0;
|
56
|
-
vector<Color> c;
|
57
|
-
c.push_back(0xffffffff);
|
58
|
-
while (pos < len) {
|
59
|
-
if (!wcsncmp(html + pos, L"<b>", 3)) {
|
60
|
-
b += 1;
|
61
|
-
pos += 3;
|
62
|
-
continue;
|
63
|
-
}
|
64
|
-
if (!wcsncmp(html + pos, L"</b>", 4)) {
|
65
|
-
b -= 1;
|
66
|
-
pos += 4;
|
67
|
-
continue;
|
68
|
-
}
|
69
|
-
if (!wcsncmp(html + pos, L"<u>", 3)) {
|
70
|
-
u += 1;
|
71
|
-
pos += 3;
|
72
|
-
continue;
|
73
|
-
}
|
74
|
-
if (!wcsncmp(html + pos, L"</u>", 4)) {
|
75
|
-
u -= 1;
|
76
|
-
pos += 4;
|
77
|
-
continue;
|
78
|
-
}
|
79
|
-
if (!wcsncmp(html + pos, L"<i>", 3)) {
|
80
|
-
i += 1;
|
81
|
-
pos += 3;
|
82
|
-
continue;
|
83
|
-
}
|
84
|
-
if (!wcsncmp(html + pos, L"</i>", 4)) {
|
85
|
-
i -= 1;
|
86
|
-
pos += 4;
|
87
|
-
continue;
|
88
|
-
}
|
89
|
-
if (!wcsncmp(html + pos, L"<c=", 3) && len >= pos + 10 && html[pos + 9] == L'>') {
|
90
|
-
unsigned rgb = static_cast<uint32_t>(wcstoul(html + pos + 3, 0, 16));
|
91
|
-
c.push_back(0xff000000 | rgb);
|
92
|
-
pos += 10;
|
93
|
-
continue;
|
94
|
-
}
|
95
|
-
if (!wcsncmp(html + pos, L"<c=", 3) && len >= pos + 12 && html[pos + 11] == L'>') {
|
96
|
-
unsigned argb = static_cast<uint32_t>(wcstoul(html + pos + 3, 0, 16));
|
97
|
-
c.push_back(argb);
|
98
|
-
pos += 12;
|
99
|
-
continue;
|
100
|
-
}
|
101
|
-
if (!wcsncmp(html + pos, L"</c>", 4)) {
|
102
|
-
if (c.size() > 1) {
|
103
|
-
c.pop_back();
|
104
|
-
}
|
105
|
-
pos += 4;
|
106
|
-
continue;
|
107
|
-
}
|
108
|
-
if (!wcsncmp(html + pos, L"<", 4)) {
|
109
|
-
FormattedChar fc = { L'<', c.back(), flags(b, u, i) };
|
110
|
-
characters.push_back(fc);
|
111
|
-
pos += 4;
|
112
|
-
continue;
|
113
|
-
}
|
114
|
-
if (!wcsncmp(html + pos, L">", 4)) {
|
115
|
-
FormattedChar fc = { L'>', c.back(), flags(b, u, i) };
|
116
|
-
characters.push_back(fc);
|
117
|
-
pos += 4;
|
118
|
-
continue;
|
119
|
-
}
|
120
|
-
if (!wcsncmp(html + pos, L"&", 5)) {
|
121
|
-
FormattedChar fc = { L'&', c.back(), flags(b, u, i) };
|
122
|
-
characters.push_back(fc);
|
123
|
-
pos += 5;
|
124
|
-
continue;
|
125
|
-
}
|
126
|
-
if (html[pos] == L'&' && html[pos + 1]) {
|
127
|
-
int end_of_entity = pos + 1;
|
128
|
-
while (html[end_of_entity] != L';') {
|
129
|
-
if (!iswalnum(static_cast<wint_t>(html[end_of_entity]))) {
|
130
|
-
goto normal_character;
|
131
|
-
}
|
132
|
-
end_of_entity += 1;
|
133
|
-
if (end_of_entity >= len) {
|
134
|
-
goto normal_character;
|
135
|
-
}
|
136
|
-
}
|
137
|
-
wstring entity(html + pos + 1, html + end_of_entity);
|
138
|
-
FormattedChar fc = { 0, c.back(), 0, wstring_to_utf8(entity) };
|
139
|
-
if (!is_entity(fc.entity)) {
|
140
|
-
goto normal_character;
|
141
|
-
}
|
142
|
-
characters.push_back(fc);
|
143
|
-
pos = end_of_entity + 1;
|
144
|
-
continue;
|
145
|
-
}
|
146
|
-
|
147
|
-
normal_character:
|
148
|
-
FormattedChar fc = { html[pos], c.back(), flags(b, u, i) };
|
149
|
-
characters.push_back(fc);
|
150
|
-
pos += 1;
|
151
|
-
}
|
152
|
-
}
|
153
|
-
|
154
|
-
wstring Gosu::FormattedString::unformat() const
|
155
|
-
{
|
156
|
-
if (characters.empty()) return simple_string;
|
157
|
-
|
158
|
-
wstring result(characters.size(), 0);
|
159
|
-
for (int i = 0; i < characters.size(); ++i) {
|
160
|
-
result[i] = characters[i].wc;
|
161
|
-
}
|
162
|
-
return result;
|
163
|
-
}
|
164
|
-
|
165
|
-
const char* Gosu::FormattedString::entity_at(unsigned index) const
|
166
|
-
{
|
167
|
-
if (characters.empty()) return nullptr;
|
168
|
-
if (characters[index].wc != 0) return nullptr;
|
169
|
-
if (characters[index].entity.empty()) return nullptr;
|
170
|
-
|
171
|
-
return characters[index].entity.c_str();
|
172
|
-
}
|
173
|
-
|
174
|
-
wchar_t Gosu::FormattedString::char_at(unsigned index) const
|
175
|
-
{
|
176
|
-
return characters.empty() ? simple_string[index] : characters[index].wc;
|
177
|
-
}
|
178
|
-
|
179
|
-
unsigned Gosu::FormattedString::flags_at(unsigned index) const
|
180
|
-
{
|
181
|
-
return characters.empty() ? simple_flags : characters[index].flags;
|
182
|
-
}
|
183
|
-
|
184
|
-
Gosu::Color Gosu::FormattedString::color_at(unsigned index) const
|
185
|
-
{
|
186
|
-
return characters.empty() ? Color::WHITE : characters[index].color;
|
187
|
-
}
|
188
|
-
|
189
|
-
size_t Gosu::FormattedString::length() const
|
190
|
-
{
|
191
|
-
return characters.empty() ? simple_string.length() : characters.size();
|
192
|
-
}
|
193
|
-
|
194
|
-
Gosu::FormattedString Gosu::FormattedString::range(size_t begin, size_t end) const
|
195
|
-
{
|
196
|
-
FormattedString result;
|
197
|
-
if (characters.empty()) {
|
198
|
-
result.simple_string.assign(simple_string.begin() + begin,
|
199
|
-
simple_string.begin() + end);
|
200
|
-
result.simple_flags = simple_flags;
|
201
|
-
}
|
202
|
-
else {
|
203
|
-
result.characters.assign(characters.begin() + begin,
|
204
|
-
characters.begin() + end);
|
205
|
-
}
|
206
|
-
return result;
|
207
|
-
}
|
208
|
-
|
209
|
-
vector<Gosu::FormattedString> Gosu::FormattedString::split_lines() const
|
210
|
-
{
|
211
|
-
vector<FormattedString> result;
|
212
|
-
unsigned begin = 0;
|
213
|
-
for (unsigned cur = 0; cur < length(); ++cur) {
|
214
|
-
if (char_at(cur) == L'\n') {
|
215
|
-
result.push_back(range(begin, cur));
|
216
|
-
begin = cur + 1;
|
217
|
-
}
|
218
|
-
}
|
219
|
-
result.push_back(range(begin, length()));
|
220
|
-
return result;
|
221
|
-
}
|
222
|
-
|
223
|
-
vector<Gosu::FormattedString> Gosu::FormattedString::split_parts() const
|
224
|
-
{
|
225
|
-
if (characters.empty()) return vector<FormattedString>(1, *this);
|
226
|
-
|
227
|
-
vector<FormattedString> result;
|
228
|
-
unsigned begin = 0;
|
229
|
-
for (unsigned cur = 1; cur < length(); ++cur) {
|
230
|
-
if (!characters[begin].same_style_as(characters[cur])) {
|
231
|
-
result.push_back(range(begin, cur));
|
232
|
-
begin = cur;
|
233
|
-
}
|
234
|
-
}
|
235
|
-
result.push_back(range(begin, length()));
|
236
|
-
return result;
|
237
|
-
}
|
data/src/FormattedString.hpp
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
#pragma once
|
2
|
-
|
3
|
-
#include "GraphicsImpl.hpp"
|
4
|
-
#include <Gosu/Color.hpp>
|
5
|
-
#include <Gosu/GraphicsBase.hpp>
|
6
|
-
#include <vector>
|
7
|
-
|
8
|
-
namespace Gosu
|
9
|
-
{
|
10
|
-
class FormattedString
|
11
|
-
{
|
12
|
-
struct FormattedChar
|
13
|
-
{
|
14
|
-
wchar_t wc;
|
15
|
-
Color color;
|
16
|
-
unsigned flags;
|
17
|
-
std::string entity;
|
18
|
-
|
19
|
-
bool same_style_as(const FormattedChar& other) const;
|
20
|
-
};
|
21
|
-
|
22
|
-
// If characters.empty(), use these for the whole string.
|
23
|
-
std::wstring simple_string;
|
24
|
-
unsigned simple_flags;
|
25
|
-
// If not characters.empty(), ignore above fields and use this.
|
26
|
-
std::vector<FormattedChar> characters;
|
27
|
-
|
28
|
-
public:
|
29
|
-
FormattedString();
|
30
|
-
FormattedString(const wchar_t* html, unsigned base_flags);
|
31
|
-
|
32
|
-
std::wstring unformat() const;
|
33
|
-
|
34
|
-
const char* entity_at(unsigned index) const;
|
35
|
-
wchar_t char_at(unsigned index) const;
|
36
|
-
unsigned flags_at(unsigned index) const;
|
37
|
-
Color color_at(unsigned index) const;
|
38
|
-
|
39
|
-
std::size_t length() const;
|
40
|
-
|
41
|
-
FormattedString range(std::size_t begin, std::size_t end) const;
|
42
|
-
|
43
|
-
std::vector<FormattedString> split_lines() const;
|
44
|
-
std::vector<FormattedString> split_parts() const;
|
45
|
-
};
|
46
|
-
}
|
47
|
-
|
data/src/GosuAppDelegate.cpp
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
#include <Gosu/Platform.hpp>
|
2
|
-
#if defined(GOSU_IS_IPHONE)
|
3
|
-
|
4
|
-
#import "GosuAppDelegate.h"
|
5
|
-
#import <Gosu/Gosu.hpp>
|
6
|
-
|
7
|
-
Gosu::Window& window_instance();
|
8
|
-
|
9
|
-
@implementation GosuAppDelegate
|
10
|
-
|
11
|
-
- (BOOL)application:(UIApplication*)application
|
12
|
-
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
|
13
|
-
{
|
14
|
-
self.window = (__bridge UIWindow*) window_instance().UIWindow();
|
15
|
-
[self.window makeKeyAndVisible];
|
16
|
-
|
17
|
-
return YES;
|
18
|
-
}
|
19
|
-
|
20
|
-
@end
|
21
|
-
|
22
|
-
int main(int argc, char* argv[])
|
23
|
-
{
|
24
|
-
@autoreleasepool {
|
25
|
-
Gosu::use_resource_directory();
|
26
|
-
return UIApplicationMain(argc, argv, nil, NSStringFromClass([GosuAppDelegate class]));
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
#endif
|
data/src/GosuAppDelegate.h
DELETED
data/src/GosuGLView.h
DELETED
data/src/TextApple.cpp
DELETED
@@ -1,212 +0,0 @@
|
|
1
|
-
#include <Gosu/Platform.hpp>
|
2
|
-
#if defined(GOSU_IS_MAC)
|
3
|
-
|
4
|
-
#include <Gosu/Text.hpp>
|
5
|
-
#include <Gosu/Bitmap.hpp>
|
6
|
-
#include <Gosu/Math.hpp>
|
7
|
-
#include <Gosu/Utility.hpp>
|
8
|
-
#include <cmath>
|
9
|
-
#include <map>
|
10
|
-
|
11
|
-
#if defined(GOSU_IS_IPHONE)
|
12
|
-
#import <CoreGraphics/CoreGraphics.h>
|
13
|
-
#import <UIKit/UIKit.h>
|
14
|
-
typedef UIFont AppleFont;
|
15
|
-
#else
|
16
|
-
#import <AppKit/AppKit.h>
|
17
|
-
typedef NSFont AppleFont;
|
18
|
-
#endif
|
19
|
-
|
20
|
-
using namespace std;
|
21
|
-
|
22
|
-
// If a font is a filename, loads the font and returns its family name that can be used
|
23
|
-
// like any system font. Otherwise, just returns the family name.
|
24
|
-
static string normalize_font(const string& font_name)
|
25
|
-
{
|
26
|
-
#ifdef GOSU_IS_IPHONE
|
27
|
-
// On iOS, we have no support for loading font files yet. However, if you register your fonts
|
28
|
-
// via your app's Info.plist, you should be able to reference them by name.
|
29
|
-
return font_name;
|
30
|
-
#else
|
31
|
-
static map<string, string> family_of_files;
|
32
|
-
|
33
|
-
// Not a path name: It is already a family name.
|
34
|
-
if (font_name.find("/") == font_name.npos) {
|
35
|
-
return font_name;
|
36
|
-
}
|
37
|
-
|
38
|
-
// Already activated font & extracted family name.
|
39
|
-
if (family_of_files.count(font_name) > 0) {
|
40
|
-
return family_of_files[font_name];
|
41
|
-
}
|
42
|
-
|
43
|
-
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:font_name.c_str()]
|
44
|
-
isDirectory:NO];
|
45
|
-
if (url == nullptr) {
|
46
|
-
return family_of_files[font_name] = Gosu::default_font_name();
|
47
|
-
}
|
48
|
-
CFURLRef url_ref = (__bridge CFURLRef) url;
|
49
|
-
|
50
|
-
NSArray* descriptors = CFBridgingRelease(CTFontManagerCreateFontDescriptorsFromURL(url_ref));
|
51
|
-
if (descriptors.count < 1 ||
|
52
|
-
!CTFontManagerRegisterFontsForURL(url_ref, kCTFontManagerScopeProcess, nullptr)) {
|
53
|
-
return family_of_files[font_name] = Gosu::default_font_name();
|
54
|
-
}
|
55
|
-
|
56
|
-
CTFontDescriptorRef ref = (__bridge CTFontDescriptorRef) descriptors[0];
|
57
|
-
CFTypeRef family_name_ref = CTFontDescriptorCopyAttribute(ref, kCTFontFamilyNameAttribute);
|
58
|
-
NSString* family_name = CFBridgingRelease(family_name_ref);
|
59
|
-
return family_of_files[font_name] = family_name.UTF8String ?: "";
|
60
|
-
#endif
|
61
|
-
}
|
62
|
-
|
63
|
-
static AppleFont* get_font(string font_name, unsigned font_flags, double height)
|
64
|
-
{
|
65
|
-
font_name = normalize_font(font_name);
|
66
|
-
|
67
|
-
static map<pair<string, pair<unsigned, double>>, AppleFont*> used_fonts;
|
68
|
-
|
69
|
-
auto key = make_pair(font_name, make_pair(font_flags, height));
|
70
|
-
|
71
|
-
AppleFont* result = used_fonts[key];
|
72
|
-
if (!result) {
|
73
|
-
NSString* name = [NSString stringWithUTF8String:font_name.c_str()];
|
74
|
-
#ifdef GOSU_IS_IPHONE
|
75
|
-
result = [AppleFont fontWithName:name size:height];
|
76
|
-
#else
|
77
|
-
NSFontDescriptor* desc =
|
78
|
-
[[NSFontDescriptor fontDescriptorWithFontAttributes:nil] fontDescriptorWithFamily:name];
|
79
|
-
result = [NSFont fontWithDescriptor:desc size:height];
|
80
|
-
if (result && (font_flags & Gosu::FF_BOLD)) {
|
81
|
-
result =
|
82
|
-
[[NSFontManager sharedFontManager] convertFont:result toHaveTrait:NSFontBoldTrait];
|
83
|
-
}
|
84
|
-
if (result && (font_flags & Gosu::FF_ITALIC)) {
|
85
|
-
result = [[NSFontManager sharedFontManager] convertFont:result
|
86
|
-
toHaveTrait:NSFontItalicTrait];
|
87
|
-
}
|
88
|
-
#endif
|
89
|
-
if (result == nullptr) {
|
90
|
-
if (font_name != Gosu::default_font_name()) {
|
91
|
-
result = get_font(Gosu::default_font_name(), 0, height);
|
92
|
-
}
|
93
|
-
else {
|
94
|
-
throw runtime_error("Cannot load default font");
|
95
|
-
}
|
96
|
-
}
|
97
|
-
used_fonts[key] = result;
|
98
|
-
}
|
99
|
-
return result;
|
100
|
-
}
|
101
|
-
|
102
|
-
string Gosu::default_font_name()
|
103
|
-
{
|
104
|
-
return "Arial";
|
105
|
-
}
|
106
|
-
|
107
|
-
#ifndef GOSU_IS_IPHONE
|
108
|
-
static NSDictionary* attribute_dictionary(NSFont* font, unsigned font_flags)
|
109
|
-
{
|
110
|
-
auto underline_style =
|
111
|
-
(font_flags & Gosu::FF_UNDERLINE) ? NSUnderlineStyleSingle : NSUnderlineStyleNone;
|
112
|
-
return @{
|
113
|
-
NSFontAttributeName: font,
|
114
|
-
NSForegroundColorAttributeName: [NSColor whiteColor],
|
115
|
-
NSUnderlineStyleAttributeName: @(underline_style)
|
116
|
-
};
|
117
|
-
}
|
118
|
-
#endif
|
119
|
-
|
120
|
-
unsigned Gosu::text_width(const string& text, const string& font_name,
|
121
|
-
unsigned font_height, unsigned font_flags)
|
122
|
-
{
|
123
|
-
if (text.find_first_of("\r\n") != text.npos) {
|
124
|
-
throw invalid_argument("text_width cannot handle line breaks");
|
125
|
-
}
|
126
|
-
|
127
|
-
AppleFont* font = get_font(font_name, font_flags, font_height);
|
128
|
-
|
129
|
-
// This will, of course, compute a too large size; font_height is in pixels,
|
130
|
-
// the method expects point.
|
131
|
-
NSString* string = [NSString stringWithUTF8String:text.c_str()];
|
132
|
-
#ifndef GOSU_IS_IPHONE
|
133
|
-
NSDictionary* attributes = attribute_dictionary(font, font_flags);
|
134
|
-
NSSize size = [string sizeWithAttributes:attributes];
|
135
|
-
#else
|
136
|
-
CGSize size = [string sizeWithFont:font];
|
137
|
-
#endif
|
138
|
-
|
139
|
-
// Now adjust the scaling...
|
140
|
-
return ceil(size.width / size.height * font_height);
|
141
|
-
}
|
142
|
-
|
143
|
-
void Gosu::draw_text(Bitmap& bitmap, const string& text, int x, int y, Color c,
|
144
|
-
const string& font_name, unsigned font_height, unsigned font_flags)
|
145
|
-
{
|
146
|
-
if (text.find_first_of("\r\n") != text.npos) {
|
147
|
-
throw invalid_argument("the argument to draw_text cannot contain line breaks");
|
148
|
-
}
|
149
|
-
|
150
|
-
AppleFont* font = get_font(font_name, font_flags, font_height);
|
151
|
-
NSString* string = [NSString stringWithUTF8String:text.c_str()];
|
152
|
-
|
153
|
-
#ifndef GOSU_IS_IPHONE
|
154
|
-
NSDictionary* attributes = attribute_dictionary(font, font_flags);
|
155
|
-
NSSize size = [string sizeWithAttributes:attributes];
|
156
|
-
#else
|
157
|
-
CGSize size = [string sizeWithFont:font];
|
158
|
-
#endif
|
159
|
-
|
160
|
-
unsigned width = static_cast<unsigned>(round(size.width / size.height * font_height));
|
161
|
-
|
162
|
-
// Get the width and height of the image
|
163
|
-
Bitmap bmp(width, font_height, 0x00ffffff);
|
164
|
-
|
165
|
-
// Use a temporary context to draw the CGImage to the buffer.
|
166
|
-
CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
|
167
|
-
CGContextRef context = CGBitmapContextCreate(bmp.data(), bmp.width(), bmp.height(), 8,
|
168
|
-
bmp.width() * 4, color_space, kCGImageAlphaPremultipliedLast);
|
169
|
-
CGColorSpaceRelease(color_space);
|
170
|
-
#ifdef GOSU_IS_IPHONE
|
171
|
-
CGFloat color[] = { 1.f, 1.f, 1.f, 0.f };
|
172
|
-
CGContextSetStrokeColor(context, color);
|
173
|
-
CGContextSetFillColor(context, color);
|
174
|
-
#endif
|
175
|
-
|
176
|
-
// Use new font with proper size this time.
|
177
|
-
font = get_font(font_name, font_flags, font_height * font_height / size.height);
|
178
|
-
|
179
|
-
#ifdef GOSU_IS_IPHONE
|
180
|
-
CGContextTranslateCTM(context, 0, font_height);
|
181
|
-
CGContextScaleCTM(context, 1, -1);
|
182
|
-
UIGraphicsPushContext(context);
|
183
|
-
[string drawAtPoint:CGPointZero withFont:font];
|
184
|
-
UIGraphicsPopContext();
|
185
|
-
#else
|
186
|
-
NSPoint NSPointZero = { 0, 0 };
|
187
|
-
attributes = attribute_dictionary(font, font_flags);
|
188
|
-
|
189
|
-
[NSGraphicsContext saveGraphicsState];
|
190
|
-
[NSGraphicsContext
|
191
|
-
setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:(void*)context
|
192
|
-
flipped:false]];
|
193
|
-
[string drawAtPoint:NSPointZero withAttributes:attributes];
|
194
|
-
[NSGraphicsContext restoreGraphicsState];
|
195
|
-
#endif
|
196
|
-
CGContextRelease(context);
|
197
|
-
|
198
|
-
int effective_width = Gosu::clamp<int>(width, 0, bitmap.width() - x);
|
199
|
-
int effective_height = Gosu::clamp<int>(font_height, 0, bitmap.height() - y);
|
200
|
-
|
201
|
-
// Now copy the set pixels back.
|
202
|
-
for (int rel_y = 0; rel_y < effective_height; ++rel_y) {
|
203
|
-
for (int rel_x = 0; rel_x < effective_width; ++rel_x) {
|
204
|
-
c.set_alpha(bmp.get_pixel(rel_x, rel_y).alpha());
|
205
|
-
if (c.alpha()) {
|
206
|
-
bitmap.set_pixel(x + rel_x, y + rel_y, c);
|
207
|
-
}
|
208
|
-
}
|
209
|
-
}
|
210
|
-
}
|
211
|
-
|
212
|
-
#endif
|