gosu 0.7.12 → 0.7.13
Sign up to get free protection for your applications and to get access to all the features.
- data/Gosu/Audio.hpp +1 -0
- data/Gosu/Bitmap.hpp +4 -4
- data/Gosu/Graphics.hpp +3 -0
- data/Gosu/Input.hpp +10 -0
- data/Gosu/Text.hpp +1 -0
- data/Gosu/Window.hpp +20 -9
- data/GosuImpl/Audio/ALChannelManagement.hpp +72 -0
- data/GosuImpl/Audio/AudioFileMac.hpp +105 -0
- data/GosuImpl/AudioOpenAL.mm +486 -0
- data/GosuImpl/DirectoriesTouch.mm +38 -0
- data/GosuImpl/Graphics/BitmapBMP.cpp +23 -8
- data/GosuImpl/Graphics/BitmapTouch.mm +73 -0
- data/GosuImpl/Graphics/BitmapUtils.cpp +0 -2
- data/GosuImpl/Graphics/BlockAllocator.cpp +15 -4
- data/GosuImpl/Graphics/Common.hpp +21 -0
- data/GosuImpl/Graphics/DrawOp.hpp +53 -10
- data/GosuImpl/Graphics/GosuView.hpp +28 -0
- data/GosuImpl/Graphics/GosuView.mm +159 -0
- data/GosuImpl/Graphics/Graphics.cpp +18 -18
- data/GosuImpl/Graphics/LargeImageData.cpp +3 -0
- data/GosuImpl/Graphics/TexChunk.cpp +3 -2
- data/GosuImpl/Graphics/Text.cpp +85 -20
- data/GosuImpl/Graphics/TextMac.cpp +14 -27
- data/GosuImpl/Graphics/TextTouch.mm +89 -0
- data/GosuImpl/Graphics/Texture.cpp +1 -5
- data/GosuImpl/Iconv.hpp +5 -3
- data/GosuImpl/InputMac.mm +8 -9
- data/GosuImpl/InputTouch.mm +47 -0
- data/GosuImpl/InputWin.cpp +12 -4
- data/GosuImpl/InputX.cpp +3 -1
- data/GosuImpl/MacUtility.hpp +41 -0
- data/GosuImpl/Math.cpp +1 -1
- data/GosuImpl/RubyGosu.swg +17 -6
- data/GosuImpl/RubyGosu_wrap.cxx +950 -549
- data/GosuImpl/RubyGosu_wrap.h +2 -1
- data/GosuImpl/TimingUnix.cpp +15 -17
- data/GosuImpl/UtilityTouch.mm +44 -0
- data/GosuImpl/WindowMac.mm +39 -19
- data/GosuImpl/WindowTouch.mm +154 -0
- data/GosuImpl/WindowWin.cpp +27 -10
- data/GosuImpl/WindowX.cpp +27 -7
- data/linux/extconf.rb +6 -0
- data/mac/Gosu.icns +0 -0
- data/mac/Gosu.xcodeproj/jlnr.pbxuser +562 -788
- data/mac/Gosu.xcodeproj/jlnr.perspectivev3 +113 -103
- data/mac/Gosu.xcodeproj/project.pbxproj +258 -173
- data/reference/Async_8hpp-source.html +1 -1
- data/reference/Audio_8hpp-source.html +91 -90
- data/reference/Audio_8hpp.html +1 -1
- data/reference/AutoLink_8hpp-source.html +1 -1
- data/reference/AutoLink_8hpp.html +1 -1
- data/reference/Bitmap_8hpp-source.html +11 -12
- data/reference/Bitmap_8hpp.html +1 -1
- data/reference/ButtonsMac_8hpp-source.html +1 -1
- data/reference/ButtonsWin_8hpp-source.html +1 -1
- data/reference/ButtonsX_8hpp-source.html +1 -1
- data/reference/Color_8hpp-source.html +1 -1
- data/reference/Color_8hpp.html +1 -1
- data/reference/Directories_8hpp-source.html +1 -1
- data/reference/Directories_8hpp.html +1 -1
- data/reference/Font_8hpp-source.html +1 -1
- data/reference/Font_8hpp.html +1 -1
- data/reference/Fwd_8hpp-source.html +1 -1
- data/reference/Fwd_8hpp.html +1 -1
- data/reference/Gosu_8hpp-source.html +1 -1
- data/reference/Gosu_8hpp.html +1 -1
- data/reference/GraphicsBase_8hpp-source.html +1 -1
- data/reference/GraphicsBase_8hpp.html +1 -1
- data/reference/Graphics_8hpp-source.html +64 -61
- data/reference/Graphics_8hpp.html +8 -1
- data/reference/IO_8hpp-source.html +1 -1
- data/reference/IO_8hpp.html +1 -1
- data/reference/ImageData_8hpp-source.html +1 -1
- data/reference/ImageData_8hpp.html +1 -1
- data/reference/Image_8hpp-source.html +1 -1
- data/reference/Image_8hpp.html +1 -1
- data/reference/Input_8hpp-source.html +81 -71
- data/reference/Input_8hpp.html +7 -1
- data/reference/Math_8hpp-source.html +1 -1
- data/reference/Math_8hpp.html +1 -1
- data/reference/Platform_8hpp-source.html +1 -1
- data/reference/Platform_8hpp.html +1 -1
- data/reference/RotFlip_8hpp-source.html +1 -1
- data/reference/RotFlip_8hpp.html +1 -1
- data/reference/Sockets_8hpp-source.html +1 -1
- data/reference/Sockets_8hpp.html +1 -1
- data/reference/TextInput_8hpp-source.html +1 -1
- data/reference/TextInput_8hpp.html +1 -1
- data/reference/Text_8hpp-source.html +28 -27
- data/reference/Text_8hpp.html +1 -1
- data/reference/Timing_8hpp-source.html +1 -1
- data/reference/Timing_8hpp.html +1 -1
- data/reference/Utility_8hpp-source.html +1 -1
- data/reference/Utility_8hpp.html +1 -1
- data/reference/WinUtility_8hpp-source.html +1 -1
- data/reference/WinUtility_8hpp.html +1 -1
- data/reference/Window_8hpp-source.html +76 -68
- data/reference/Window_8hpp.html +1 -1
- data/reference/annotated.html +1 -1
- data/reference/classGosu_1_1Audio-members.html +1 -1
- data/reference/classGosu_1_1Audio.html +1 -1
- data/reference/classGosu_1_1Bitmap-members.html +3 -2
- data/reference/classGosu_1_1Bitmap.html +9 -6
- data/reference/classGosu_1_1Buffer-members.html +1 -1
- data/reference/classGosu_1_1Buffer.html +1 -1
- data/reference/classGosu_1_1Button-members.html +1 -1
- data/reference/classGosu_1_1Button.html +2 -2
- data/reference/classGosu_1_1Color-members.html +1 -1
- data/reference/classGosu_1_1Color.html +1 -1
- data/reference/classGosu_1_1File-members.html +1 -1
- data/reference/classGosu_1_1File.html +1 -1
- data/reference/classGosu_1_1Font-members.html +1 -1
- data/reference/classGosu_1_1Font.html +1 -1
- data/reference/classGosu_1_1Graphics-members.html +1 -1
- data/reference/classGosu_1_1Graphics.html +1 -1
- data/reference/classGosu_1_1Image-members.html +1 -1
- data/reference/classGosu_1_1Image.html +1 -1
- data/reference/classGosu_1_1ImageData-members.html +1 -1
- data/reference/classGosu_1_1ImageData.html +1 -1
- data/reference/classGosu_1_1Input-members.html +1 -1
- data/reference/classGosu_1_1Input.html +1 -1
- data/reference/classGosu_1_1MessageSocket-members.html +1 -1
- data/reference/classGosu_1_1MessageSocket.html +1 -1
- data/reference/classGosu_1_1Resource-members.html +1 -1
- data/reference/classGosu_1_1Resource.html +1 -1
- data/reference/classGosu_1_1Sample-members.html +1 -1
- data/reference/classGosu_1_1Sample.html +1 -1
- data/reference/classGosu_1_1SampleInstance-members.html +1 -1
- data/reference/classGosu_1_1SampleInstance.html +1 -1
- data/reference/classGosu_1_1Song-members.html +1 -1
- data/reference/classGosu_1_1Song.html +1 -1
- data/reference/classGosu_1_1TextInput-members.html +1 -1
- data/reference/classGosu_1_1TextInput.html +1 -1
- data/reference/classGosu_1_1Window-members.html +3 -3
- data/reference/classGosu_1_1Window.html +27 -9
- data/reference/files.html +1 -1
- data/reference/functions.html +10 -5
- data/reference/functions_enum.html +1 -1
- data/reference/functions_func.html +10 -5
- data/reference/functions_vars.html +1 -1
- data/reference/hierarchy.html +1 -1
- data/reference/index.html +1 -1
- data/reference/namespaceGosu.html +13 -2
- data/reference/namespaceGosu_1_1Colors.html +1 -1
- data/reference/namespaceGosu_1_1Win.html +1 -1
- data/reference/namespacemembers.html +1 -1
- data/reference/namespacemembers_enum.html +1 -1
- data/reference/namespacemembers_eval.html +1 -1
- data/reference/namespacemembers_func.html +1 -1
- data/reference/namespacemembers_type.html +1 -1
- data/reference/namespacemembers_vars.html +1 -1
- data/reference/namespaces.html +1 -1
- data/windows/Gosu.sln +2 -2
- data/windows/Gosu.vcproj +7 -8
- data/windows/RubyGosu.vcproj +5 -5
- metadata +14 -2
@@ -30,18 +30,18 @@ struct Gosu::Graphics::Impl
|
|
30
30
|
Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscreen)
|
31
31
|
: pimpl(new Impl)
|
32
32
|
{
|
33
|
-
pimpl->
|
34
|
-
pimpl->
|
33
|
+
pimpl->virtWidth = pimpl->physWidth = physWidth;
|
34
|
+
pimpl->virtHeight = pimpl->physHeight = physHeight;
|
35
35
|
pimpl->factorX = pimpl->factorY = 1.0;
|
36
36
|
pimpl->fullscreen = fullscreen;
|
37
|
-
|
37
|
+
|
38
38
|
glMatrixMode(GL_PROJECTION);
|
39
39
|
glLoadIdentity();
|
40
40
|
glViewport(0, 0, pimpl->physWidth, pimpl->physHeight);
|
41
41
|
#ifdef GOSU_IS_IPHONE
|
42
|
-
glOrthof(0, pimpl->
|
42
|
+
glOrthof(0, pimpl->physWidth, pimpl->physHeight, 0, -1, 1);
|
43
43
|
#else
|
44
|
-
glOrtho(0, pimpl->
|
44
|
+
glOrtho(0, pimpl->physWidth, pimpl->physHeight, 0, -1, 1);
|
45
45
|
#endif
|
46
46
|
|
47
47
|
glMatrixMode(GL_MODELVIEW);
|
@@ -49,6 +49,7 @@ Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscree
|
|
49
49
|
#ifdef GOSU_IS_IPHONE
|
50
50
|
glTranslatef(physWidth, 0, 0);
|
51
51
|
glRotatef(90, 0, 0, 1);
|
52
|
+
glScalef(3.0/2, 2.0/3, 0);
|
52
53
|
#endif
|
53
54
|
|
54
55
|
glEnable(GL_BLEND);
|
@@ -101,10 +102,8 @@ void Gosu::Graphics::setResolution(unsigned virtualWidth, unsigned virtualHeight
|
|
101
102
|
|
102
103
|
bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
|
103
104
|
{
|
104
|
-
#ifndef GOSU_IS_IPHONE
|
105
105
|
// Flush leftover clippings
|
106
106
|
endClipping();
|
107
|
-
#endif
|
108
107
|
|
109
108
|
glClearColor(clearWithColor.red()/255.0,
|
110
109
|
clearWithColor.green()/255.0,
|
@@ -171,27 +170,27 @@ void Gosu::Graphics::endGL()
|
|
171
170
|
|
172
171
|
void Gosu::Graphics::beginClipping(int x, int y, unsigned width, unsigned height)
|
173
172
|
{
|
174
|
-
#ifdef GOSU_IS_IPHONE
|
175
|
-
throw std::logic_error("Clipping is unsupported on the iPhone");
|
176
|
-
#else
|
177
173
|
// In doubt, make the clipping region smaller than requested.
|
178
174
|
|
175
|
+
#ifndef GOSU_IS_IPHONE
|
179
176
|
int physX = static_cast<int>(std::ceil(x * factorX()));
|
180
177
|
int physY = static_cast<int>(std::ceil((0.0 + this->height() - y - height) * factorY()));
|
181
178
|
unsigned physWidth = static_cast<unsigned>(width * factorX());
|
182
179
|
unsigned physHeight = static_cast<unsigned>(height * factorY());
|
180
|
+
#else
|
181
|
+
// Make up for rotation
|
182
|
+
int physX = 320 - static_cast<int>(std::ceil(320.0 * (0.0 + y + height) / this->height()));
|
183
|
+
int physY = 480 - static_cast<int>(std::ceil(480.0 * (0.0 + x + width) / this->width()));
|
184
|
+
unsigned physWidth = static_cast<unsigned>(320.0 * height / this->height());
|
185
|
+
unsigned physHeight = static_cast<unsigned>(480.0 * width / this->width());
|
186
|
+
#endif
|
183
187
|
|
184
188
|
pimpl->queue.beginClipping(physX, physY, physWidth, physHeight);
|
185
|
-
#endif
|
186
189
|
}
|
187
190
|
|
188
191
|
void Gosu::Graphics::endClipping()
|
189
192
|
{
|
190
|
-
#ifdef GOSU_IS_IPHONE
|
191
|
-
throw std::logic_error("Clipping is unsupported on the iPhone");
|
192
|
-
#else
|
193
193
|
pimpl->queue.endClipping();
|
194
|
-
#endif
|
195
194
|
}
|
196
195
|
|
197
196
|
void Gosu::Graphics::drawLine(double x1, double y1, Color c1,
|
@@ -242,6 +241,8 @@ void Gosu::Graphics::drawQuad(double x1, double y1, Color c1,
|
|
242
241
|
double x4, double y4, Color c4,
|
243
242
|
ZPos z, AlphaMode mode)
|
244
243
|
{
|
244
|
+
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, x4, y4);
|
245
|
+
|
245
246
|
DrawOp op;
|
246
247
|
|
247
248
|
x1 *= factorX();
|
@@ -278,9 +279,8 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
|
|
278
279
|
// Special case: If the texture is supposed to have hard borders,
|
279
280
|
// is quadratic, has a size that is at least 64 pixels but less than 256
|
280
281
|
// pixels and a power of two, create a single texture just for this image.
|
281
|
-
|
282
|
+
if ((borderFlags & bfHard) == bfHard &&
|
282
283
|
srcWidth == srcHeight &&
|
283
|
-
srcWidth >= 64 && srcWidth <= 256 &&
|
284
284
|
(srcWidth & (srcWidth - 1)) == 0)
|
285
285
|
{
|
286
286
|
boost::shared_ptr<Texture> texture(new Texture(srcWidth));
|
@@ -306,7 +306,7 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
|
|
306
306
|
if (!data.get())
|
307
307
|
throw std::logic_error("Internal texture block allocation error");
|
308
308
|
return data;
|
309
|
-
}
|
309
|
+
}
|
310
310
|
|
311
311
|
// Too large to fit on a single texture.
|
312
312
|
if (srcWidth > maxSize - 2 || srcHeight > maxSize - 2)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#include <GosuImpl/Graphics/LargeImageData.hpp>
|
2
|
+
#include <GosuImpl/Graphics/Common.hpp>
|
2
3
|
#include <Gosu/Bitmap.hpp>
|
3
4
|
#include <Gosu/Graphics.hpp>
|
4
5
|
#include <Gosu/Math.hpp>
|
@@ -84,6 +85,8 @@ void Gosu::LargeImageData::draw(double x1, double y1, Color c1,
|
|
84
85
|
if (parts.empty())
|
85
86
|
return;
|
86
87
|
|
88
|
+
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, x4, y4);
|
89
|
+
|
87
90
|
for (unsigned py = 0; py < partsY; ++py)
|
88
91
|
for (unsigned px = 0; px < partsX; ++px)
|
89
92
|
{
|
@@ -46,7 +46,9 @@ void Gosu::TexChunk::draw(double x1, double y1, Color c1,
|
|
46
46
|
ZPos z, AlphaMode mode) const
|
47
47
|
{
|
48
48
|
DrawOp newDrawOp;
|
49
|
-
|
49
|
+
|
50
|
+
reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, x4, y4);
|
51
|
+
|
50
52
|
x1 *= graphics->factorX();
|
51
53
|
y1 *= graphics->factorY();
|
52
54
|
x2 *= graphics->factorX();
|
@@ -73,7 +75,6 @@ void Gosu::TexChunk::draw(double x1, double y1, Color c1,
|
|
73
75
|
queue->addDrawOp(newDrawOp, z);
|
74
76
|
}
|
75
77
|
|
76
|
-
|
77
78
|
boost::optional<Gosu::GLTexInfo> Gosu::TexChunk::glTexInfo() const
|
78
79
|
{
|
79
80
|
Gosu::GLTexInfo info;
|
data/GosuImpl/Graphics/Text.cpp
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#include <Gosu/Graphics.hpp>
|
4
4
|
#include <Gosu/Image.hpp>
|
5
5
|
#include <Gosu/Math.hpp>
|
6
|
+
#include <Gosu/Utility.hpp>
|
6
7
|
#include <boost/bind.hpp>
|
7
8
|
#include <boost/algorithm/string.hpp>
|
8
9
|
#include <boost/tokenizer.hpp>
|
@@ -16,10 +17,30 @@ namespace Gosu
|
|
16
17
|
{
|
17
18
|
namespace
|
18
19
|
{
|
20
|
+
// Just a very simple heuristic that should make Chinese and Japanese text working in most
|
21
|
+
// of the cases.
|
22
|
+
bool isBreakingAsianGlyph(wchar_t ch)
|
23
|
+
{
|
24
|
+
if (ch >= 0x3040 && ch <= 0x3096)
|
25
|
+
return true; // Hiragana
|
26
|
+
|
27
|
+
if (ch >= 0x30a0 && ch <= 0x30fa)
|
28
|
+
return true; // Katakana
|
29
|
+
|
30
|
+
if (ch >= 0x4e00 && ch <= 0x9fff)
|
31
|
+
return true; // CJK Unified Ideographs
|
32
|
+
|
33
|
+
if (ch >= 0x3400 && ch <= 0x4db5)
|
34
|
+
return true; // CJK Unified Ideographs Extension A
|
35
|
+
|
36
|
+
return false;
|
37
|
+
}
|
38
|
+
|
19
39
|
struct WordInfo
|
20
40
|
{
|
21
41
|
wstring text;
|
22
42
|
unsigned width;
|
43
|
+
unsigned spaceWidth;
|
23
44
|
};
|
24
45
|
typedef vector<WordInfo> Words;
|
25
46
|
|
@@ -83,6 +104,10 @@ namespace Gosu
|
|
83
104
|
allocNextLine();
|
84
105
|
|
85
106
|
unsigned words = end - begin;
|
107
|
+
|
108
|
+
unsigned totalSpacing = 0;
|
109
|
+
for (Words::const_iterator i = begin; i != end - 1; ++i)
|
110
|
+
totalSpacing += i->spaceWidth;
|
86
111
|
|
87
112
|
// Where does the line start? (y)
|
88
113
|
unsigned top = (usedLines - 1) * (fontHeight + lineSpacing);
|
@@ -93,12 +118,12 @@ namespace Gosu
|
|
93
118
|
{
|
94
119
|
// Start so that the text touches the right border.
|
95
120
|
case taRight:
|
96
|
-
pos = bmp.width() - wordsWidth -
|
121
|
+
pos = bmp.width() - wordsWidth - totalSpacing;
|
97
122
|
break;
|
98
123
|
|
99
124
|
// Start so that the text is centered.
|
100
125
|
case taCenter:
|
101
|
-
pos = bmp.width() - wordsWidth -
|
126
|
+
pos = bmp.width() - wordsWidth - totalSpacing;
|
102
127
|
pos /= 2;
|
103
128
|
break;
|
104
129
|
|
@@ -107,20 +132,22 @@ namespace Gosu
|
|
107
132
|
pos = 0;
|
108
133
|
}
|
109
134
|
|
110
|
-
// How much space is between each word?
|
111
|
-
double spacing;
|
112
|
-
if (align == taJustify && !overrideAlign)
|
113
|
-
spacing = (bmp.width() - wordsWidth) / (words - 1.0);
|
114
|
-
else
|
115
|
-
spacing = spaceWidth;
|
116
|
-
|
117
135
|
for (Words::const_iterator cur = begin; cur != end; ++cur)
|
118
136
|
{
|
119
137
|
drawText(bmp, cur->text, trunc(pos), trunc(top),
|
120
138
|
Colors::white, fontName, fontHeight, fontFlags);
|
121
|
-
|
139
|
+
|
140
|
+
if (align == taJustify && !overrideAlign)
|
141
|
+
pos += cur->width + 1.0 * (width() - wordsWidth) / (words - 1);
|
142
|
+
else
|
143
|
+
pos += cur->width + cur->spaceWidth;
|
122
144
|
}
|
123
145
|
}
|
146
|
+
|
147
|
+
void addEmptyLine()
|
148
|
+
{
|
149
|
+
allocNextLine();
|
150
|
+
}
|
124
151
|
|
125
152
|
Bitmap result() const
|
126
153
|
{
|
@@ -133,11 +160,12 @@ namespace Gosu
|
|
133
160
|
|
134
161
|
void processWords(TextBlockBuilder& builder, const Words& words)
|
135
162
|
{
|
163
|
+
if (words.empty())
|
164
|
+
return builder.addEmptyLine();
|
165
|
+
|
136
166
|
// Index into words to the first word in the current line.
|
137
167
|
Words::const_iterator lineBegin = words.begin();
|
138
168
|
|
139
|
-
const unsigned spaceWidth = builder.textWidth(L" "); // IMPR.
|
140
|
-
|
141
169
|
// Used width, in pixels, of the words [lineBegin..w[.
|
142
170
|
unsigned wordsWidth = 0;
|
143
171
|
|
@@ -153,7 +181,7 @@ namespace Gosu
|
|
153
181
|
// There's enough space for the words [lineBegin..w] plus
|
154
182
|
// the spaces between them: Proceed with the next word.
|
155
183
|
wordsWidth = newWordsWidth;
|
156
|
-
spacesWidth += spaceWidth;
|
184
|
+
spacesWidth += w->spaceWidth;
|
157
185
|
}
|
158
186
|
else
|
159
187
|
{
|
@@ -164,7 +192,7 @@ namespace Gosu
|
|
164
192
|
|
165
193
|
lineBegin = w;
|
166
194
|
wordsWidth = w->width;
|
167
|
-
spacesWidth = spaceWidth;
|
195
|
+
spacesWidth = w->spaceWidth;
|
168
196
|
}
|
169
197
|
}
|
170
198
|
|
@@ -181,14 +209,51 @@ namespace Gosu
|
|
181
209
|
{
|
182
210
|
Words collectedWords;
|
183
211
|
|
184
|
-
|
185
|
-
|
186
|
-
|
212
|
+
const unsigned spaceWidth = builder.textWidth(L" ");
|
213
|
+
|
214
|
+
unsigned beginOfWord = 0;
|
215
|
+
|
216
|
+
for (unsigned cur = 0; cur < paragraph.length(); ++cur)
|
187
217
|
{
|
188
218
|
WordInfo newWord;
|
189
|
-
|
190
|
-
|
191
|
-
|
219
|
+
|
220
|
+
if (paragraph[cur] == L' ')
|
221
|
+
{
|
222
|
+
// Whitespace: Add last word to list if existent
|
223
|
+
if (beginOfWord != cur)
|
224
|
+
{
|
225
|
+
newWord.text.assign(paragraph.begin() + beginOfWord, paragraph.begin() + cur);
|
226
|
+
newWord.width = builder.textWidth(newWord.text);
|
227
|
+
newWord.spaceWidth = spaceWidth;
|
228
|
+
collectedWords.push_back(newWord);
|
229
|
+
}
|
230
|
+
beginOfWord = cur + 1;
|
231
|
+
}
|
232
|
+
else if (isBreakingAsianGlyph(paragraph[cur]))
|
233
|
+
{
|
234
|
+
// Whitespace: Add last word to list if existent
|
235
|
+
if (beginOfWord != cur)
|
236
|
+
{
|
237
|
+
newWord.text.assign(paragraph.begin() + beginOfWord, paragraph.begin() + cur);
|
238
|
+
newWord.width = builder.textWidth(newWord.text);
|
239
|
+
newWord.spaceWidth = 0;
|
240
|
+
collectedWords.push_back(newWord);
|
241
|
+
}
|
242
|
+
// Add glyph as a single "word"
|
243
|
+
newWord.text = wstring(1, paragraph[cur]);
|
244
|
+
newWord.width = builder.textWidth(newWord.text);
|
245
|
+
newWord.spaceWidth = 0;
|
246
|
+
collectedWords.push_back(newWord);
|
247
|
+
beginOfWord = cur + 1;
|
248
|
+
}
|
249
|
+
}
|
250
|
+
if (beginOfWord < paragraph.length())
|
251
|
+
{
|
252
|
+
WordInfo lastWord;
|
253
|
+
lastWord.text.assign(paragraph.begin() + beginOfWord, paragraph.end());
|
254
|
+
lastWord.width = builder.textWidth(lastWord.text);
|
255
|
+
lastWord.spaceWidth = 0;
|
256
|
+
collectedWords.push_back(lastWord);
|
192
257
|
}
|
193
258
|
|
194
259
|
processWords(builder, collectedWords);
|
@@ -2,6 +2,7 @@
|
|
2
2
|
#include <Gosu/Text.hpp>
|
3
3
|
#include <Gosu/Utility.hpp>
|
4
4
|
#include <Gosu/IO.hpp>
|
5
|
+
#include <GosuImpl/MacUtility.hpp>
|
5
6
|
#include <boost/utility.hpp>
|
6
7
|
#include <boost/cstdint.hpp>
|
7
8
|
#include <cmath>
|
@@ -22,20 +23,6 @@ namespace Gosu
|
|
22
23
|
std::vector<unsigned short> wstringToUniChars(const std::wstring& ws);
|
23
24
|
}
|
24
25
|
|
25
|
-
#include <iostream>
|
26
|
-
#include <ostream>
|
27
|
-
#include <sstream>
|
28
|
-
void throwError(OSStatus status, unsigned line)
|
29
|
-
{
|
30
|
-
std::ostringstream str;
|
31
|
-
str << "Error on line " << line << " (Code " << status << "): "
|
32
|
-
<< GetMacOSStatusErrorString(status)
|
33
|
-
<< " (" << GetMacOSStatusCommentString(status) << ")";
|
34
|
-
throw std::runtime_error(str.str());
|
35
|
-
}
|
36
|
-
|
37
|
-
#define checkErr(status) if (!(status)) {} else throwError(status, __LINE__)
|
38
|
-
|
39
26
|
namespace
|
40
27
|
{
|
41
28
|
class MacBitmap : boost::noncopyable
|
@@ -97,13 +84,13 @@ namespace
|
|
97
84
|
Gosu::loadFile(buf, fontName);
|
98
85
|
|
99
86
|
ATSFontContainerRef container;
|
100
|
-
|
87
|
+
CHECK_OS( ATSFontActivateFromMemory(buf.data(), buf.size(),
|
101
88
|
kATSFontContextLocal, kATSFontFormatUnspecified,
|
102
89
|
NULL, kATSOptionFlagsDefault, &container) );
|
103
90
|
|
104
91
|
ATSFontRef fontRefs[1024];
|
105
92
|
ItemCount fontCount;
|
106
|
-
|
93
|
+
CHECK_OS( ATSFontFindFromContainer(container, kATSOptionFlagsDefault,
|
107
94
|
1024, fontRefs, &fontCount) );
|
108
95
|
if (fontCount == 0)
|
109
96
|
throw std::runtime_error("No font found in " + Gosu::narrow(fontName));
|
@@ -116,7 +103,7 @@ namespace
|
|
116
103
|
newFont.fontId = FMGetFontFromATSFontRef(atsRef);
|
117
104
|
|
118
105
|
ATSFontMetrics metrics;
|
119
|
-
|
106
|
+
CHECK_OS(ATSFontGetHorizontalMetrics(newFont.fontId, kATSOptionFlagsDefault, &metrics));
|
120
107
|
newFont.heightAt1Pt = metrics.ascent - metrics.descent;
|
121
108
|
newFont.descentAt1Pt = -metrics.descent;
|
122
109
|
fonts[fontName] = newFont;
|
@@ -134,7 +121,7 @@ namespace
|
|
134
121
|
{
|
135
122
|
ByteCount size = sizeof value;
|
136
123
|
ATSUAttributeValuePtr ptr = &value;
|
137
|
-
|
124
|
+
CHECK_OS( ATSUSetAttributes(style, 1, &tag, &size, &ptr) );
|
138
125
|
}
|
139
126
|
|
140
127
|
template<typename T>
|
@@ -142,7 +129,7 @@ namespace
|
|
142
129
|
{
|
143
130
|
ByteCount size = sizeof value;
|
144
131
|
ATSUAttributeValuePtr ptr = &value;
|
145
|
-
|
132
|
+
CHECK_OS( ATSUSetLayoutControls(layout, 1, &tag, &size, &ptr) );
|
146
133
|
}
|
147
134
|
|
148
135
|
public:
|
@@ -150,7 +137,7 @@ namespace
|
|
150
137
|
{
|
151
138
|
utf16 = Gosu::wstringToUniChars(text);
|
152
139
|
|
153
|
-
|
140
|
+
CHECK_OS( ATSUCreateStyle(&style) );
|
154
141
|
|
155
142
|
CachedFontInfo& font = getFont(fontName);
|
156
143
|
|
@@ -165,21 +152,21 @@ namespace
|
|
165
152
|
setAttribute<Boolean>(kATSUQDUnderlineTag, TRUE);
|
166
153
|
|
167
154
|
UniCharCount runLength = utf16.size();
|
168
|
-
|
155
|
+
CHECK_OS( ATSUCreateTextLayoutWithTextPtr(&utf16[0], kATSUFromTextBeginning,
|
169
156
|
kATSUToTextEnd, utf16.size(), 1, &runLength, &style, &layout) );
|
170
157
|
}
|
171
158
|
|
172
159
|
~ATSULayoutAndStyle()
|
173
160
|
{
|
174
|
-
|
175
|
-
|
161
|
+
CHECK_OS( ATSUDisposeStyle(style) );
|
162
|
+
CHECK_OS( ATSUDisposeTextLayout(layout) );
|
176
163
|
}
|
177
164
|
|
178
165
|
Rect textExtents() const
|
179
166
|
{
|
180
167
|
Rect rect;
|
181
|
-
|
182
|
-
|
168
|
+
CHECK_OS( ATSUSetTransientFontMatching(layout, TRUE) );
|
169
|
+
CHECK_OS( ATSUMeasureTextImage(layout, kATSUFromTextBeginning,
|
183
170
|
kATSUToTextEnd, X2Fix(0), X2Fix(0), &rect) );
|
184
171
|
return rect;
|
185
172
|
}
|
@@ -192,8 +179,8 @@ namespace
|
|
192
179
|
RGBColor color = { 0, 0, 0 };
|
193
180
|
setAttribute<RGBColor>(kATSUColorTag, color);
|
194
181
|
setLayoutControl<CGContextRef>(kATSUCGContextTag, context);
|
195
|
-
|
196
|
-
|
182
|
+
CHECK_OS( ATSUSetTransientFontMatching(layout, TRUE) );
|
183
|
+
CHECK_OS( ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, x, y) );
|
197
184
|
}
|
198
185
|
};
|
199
186
|
}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
#import <Gosu/Text.hpp>
|
2
|
+
#import <Gosu/Bitmap.hpp>
|
3
|
+
#import <Gosu/Utility.hpp>
|
4
|
+
#import <GosuImpl/MacUtility.hpp>
|
5
|
+
#import <UIKit/UIKit.h>
|
6
|
+
#import <CoreGraphics/CoreGraphics.h>
|
7
|
+
#import <map>
|
8
|
+
#import <cmath>
|
9
|
+
using namespace std;
|
10
|
+
|
11
|
+
namespace
|
12
|
+
{
|
13
|
+
map<pair<wstring, double>, UIFont*> usedFonts;
|
14
|
+
|
15
|
+
UIFont* getFont(const wstring& name, double height)
|
16
|
+
{
|
17
|
+
UIFont* result = usedFonts[make_pair(name, height)];
|
18
|
+
if (!result)
|
19
|
+
{
|
20
|
+
Gosu::ObjRef<NSString> fontName([[NSString alloc] initWithUTF8String: Gosu::wstringToUTF8(name).c_str()]);
|
21
|
+
result = [UIFont fontWithName: fontName.obj() size: height];
|
22
|
+
}
|
23
|
+
return result;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
wstring Gosu::defaultFontName()
|
28
|
+
{
|
29
|
+
// OF COURSE Helvetica is better - but the dots above my capital umlauts get
|
30
|
+
// eaten when I use it with Gosu. Until this is fixed, keep Arial. (TODO)
|
31
|
+
return L"Arial";
|
32
|
+
}
|
33
|
+
|
34
|
+
unsigned Gosu::textWidth(const wstring& text,
|
35
|
+
const wstring& fontName, unsigned fontHeight, unsigned fontFlags)
|
36
|
+
{
|
37
|
+
UIFont* font = getFont(fontName, fontHeight);
|
38
|
+
|
39
|
+
// This will, of course, compute a too large size; fontHeight is in pixels, the method expects point.
|
40
|
+
ObjRef<NSString> string([[NSString alloc] initWithUTF8String: wstringToUTF8(text).c_str()]);
|
41
|
+
CGSize size = [string.obj() sizeWithFont: font];
|
42
|
+
|
43
|
+
// Now adjust the scaling...
|
44
|
+
return ceil(size.width / size.height * fontHeight);
|
45
|
+
}
|
46
|
+
|
47
|
+
void Gosu::drawText(Bitmap& bitmap, const wstring& text, int x, int y,
|
48
|
+
Color c, const wstring& fontName, unsigned fontHeight,
|
49
|
+
unsigned fontFlags)
|
50
|
+
{
|
51
|
+
UIFont* font = getFont(fontName, fontHeight);
|
52
|
+
ObjRef<NSString> string([[NSString alloc] initWithUTF8String: wstringToUTF8(text).c_str()]);
|
53
|
+
|
54
|
+
// This will, of course, compute a too large size; fontHeight is in pixels, the method expects point.
|
55
|
+
CGSize size = [string.obj() sizeWithFont: font];
|
56
|
+
|
57
|
+
unsigned width = ceil(size.width / size.height * fontHeight);
|
58
|
+
|
59
|
+
// Get the width and height of the image
|
60
|
+
Bitmap bmp;
|
61
|
+
bmp.resize(width, fontHeight);
|
62
|
+
|
63
|
+
// Use a temporary context to draw the CGImage to the buffer.
|
64
|
+
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
65
|
+
CGContextRef context =
|
66
|
+
CGBitmapContextCreate(bmp.data(),
|
67
|
+
bmp.width(), bmp.height(), 8, bmp.width() * 4,
|
68
|
+
colorSpace,
|
69
|
+
kCGImageAlphaPremultipliedLast);
|
70
|
+
CGColorSpaceRelease(colorSpace);
|
71
|
+
CGFloat color[] = { c.green() / 255.0, c.blue() / 255.0, c.red() / 255.0, 0 };
|
72
|
+
CGContextSetStrokeColor(context, color);
|
73
|
+
CGContextSetFillColor(context, color);
|
74
|
+
|
75
|
+
// TODO: Should probably use CGShowText instead of all the ObjC bloat.
|
76
|
+
|
77
|
+
// Use new font with proper size this time.
|
78
|
+
font = getFont(fontName, fontHeight * fontHeight / size.height);
|
79
|
+
|
80
|
+
CGContextTranslateCTM(context, 0, fontHeight);
|
81
|
+
CGContextScaleCTM(context, 1, -1);
|
82
|
+
UIGraphicsPushContext(context);
|
83
|
+
[string.obj() drawAtPoint: CGPointZero withFont: font];
|
84
|
+
UIGraphicsPopContext();
|
85
|
+
CGContextRelease(context);
|
86
|
+
|
87
|
+
// Done!
|
88
|
+
bitmap.insert(bmp, x, y);
|
89
|
+
}
|