gosu 0.7.12 → 0.7.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. data/Gosu/Audio.hpp +1 -0
  2. data/Gosu/Bitmap.hpp +4 -4
  3. data/Gosu/Graphics.hpp +3 -0
  4. data/Gosu/Input.hpp +10 -0
  5. data/Gosu/Text.hpp +1 -0
  6. data/Gosu/Window.hpp +20 -9
  7. data/GosuImpl/Audio/ALChannelManagement.hpp +72 -0
  8. data/GosuImpl/Audio/AudioFileMac.hpp +105 -0
  9. data/GosuImpl/AudioOpenAL.mm +486 -0
  10. data/GosuImpl/DirectoriesTouch.mm +38 -0
  11. data/GosuImpl/Graphics/BitmapBMP.cpp +23 -8
  12. data/GosuImpl/Graphics/BitmapTouch.mm +73 -0
  13. data/GosuImpl/Graphics/BitmapUtils.cpp +0 -2
  14. data/GosuImpl/Graphics/BlockAllocator.cpp +15 -4
  15. data/GosuImpl/Graphics/Common.hpp +21 -0
  16. data/GosuImpl/Graphics/DrawOp.hpp +53 -10
  17. data/GosuImpl/Graphics/GosuView.hpp +28 -0
  18. data/GosuImpl/Graphics/GosuView.mm +159 -0
  19. data/GosuImpl/Graphics/Graphics.cpp +18 -18
  20. data/GosuImpl/Graphics/LargeImageData.cpp +3 -0
  21. data/GosuImpl/Graphics/TexChunk.cpp +3 -2
  22. data/GosuImpl/Graphics/Text.cpp +85 -20
  23. data/GosuImpl/Graphics/TextMac.cpp +14 -27
  24. data/GosuImpl/Graphics/TextTouch.mm +89 -0
  25. data/GosuImpl/Graphics/Texture.cpp +1 -5
  26. data/GosuImpl/Iconv.hpp +5 -3
  27. data/GosuImpl/InputMac.mm +8 -9
  28. data/GosuImpl/InputTouch.mm +47 -0
  29. data/GosuImpl/InputWin.cpp +12 -4
  30. data/GosuImpl/InputX.cpp +3 -1
  31. data/GosuImpl/MacUtility.hpp +41 -0
  32. data/GosuImpl/Math.cpp +1 -1
  33. data/GosuImpl/RubyGosu.swg +17 -6
  34. data/GosuImpl/RubyGosu_wrap.cxx +950 -549
  35. data/GosuImpl/RubyGosu_wrap.h +2 -1
  36. data/GosuImpl/TimingUnix.cpp +15 -17
  37. data/GosuImpl/UtilityTouch.mm +44 -0
  38. data/GosuImpl/WindowMac.mm +39 -19
  39. data/GosuImpl/WindowTouch.mm +154 -0
  40. data/GosuImpl/WindowWin.cpp +27 -10
  41. data/GosuImpl/WindowX.cpp +27 -7
  42. data/linux/extconf.rb +6 -0
  43. data/mac/Gosu.icns +0 -0
  44. data/mac/Gosu.xcodeproj/jlnr.pbxuser +562 -788
  45. data/mac/Gosu.xcodeproj/jlnr.perspectivev3 +113 -103
  46. data/mac/Gosu.xcodeproj/project.pbxproj +258 -173
  47. data/reference/Async_8hpp-source.html +1 -1
  48. data/reference/Audio_8hpp-source.html +91 -90
  49. data/reference/Audio_8hpp.html +1 -1
  50. data/reference/AutoLink_8hpp-source.html +1 -1
  51. data/reference/AutoLink_8hpp.html +1 -1
  52. data/reference/Bitmap_8hpp-source.html +11 -12
  53. data/reference/Bitmap_8hpp.html +1 -1
  54. data/reference/ButtonsMac_8hpp-source.html +1 -1
  55. data/reference/ButtonsWin_8hpp-source.html +1 -1
  56. data/reference/ButtonsX_8hpp-source.html +1 -1
  57. data/reference/Color_8hpp-source.html +1 -1
  58. data/reference/Color_8hpp.html +1 -1
  59. data/reference/Directories_8hpp-source.html +1 -1
  60. data/reference/Directories_8hpp.html +1 -1
  61. data/reference/Font_8hpp-source.html +1 -1
  62. data/reference/Font_8hpp.html +1 -1
  63. data/reference/Fwd_8hpp-source.html +1 -1
  64. data/reference/Fwd_8hpp.html +1 -1
  65. data/reference/Gosu_8hpp-source.html +1 -1
  66. data/reference/Gosu_8hpp.html +1 -1
  67. data/reference/GraphicsBase_8hpp-source.html +1 -1
  68. data/reference/GraphicsBase_8hpp.html +1 -1
  69. data/reference/Graphics_8hpp-source.html +64 -61
  70. data/reference/Graphics_8hpp.html +8 -1
  71. data/reference/IO_8hpp-source.html +1 -1
  72. data/reference/IO_8hpp.html +1 -1
  73. data/reference/ImageData_8hpp-source.html +1 -1
  74. data/reference/ImageData_8hpp.html +1 -1
  75. data/reference/Image_8hpp-source.html +1 -1
  76. data/reference/Image_8hpp.html +1 -1
  77. data/reference/Input_8hpp-source.html +81 -71
  78. data/reference/Input_8hpp.html +7 -1
  79. data/reference/Math_8hpp-source.html +1 -1
  80. data/reference/Math_8hpp.html +1 -1
  81. data/reference/Platform_8hpp-source.html +1 -1
  82. data/reference/Platform_8hpp.html +1 -1
  83. data/reference/RotFlip_8hpp-source.html +1 -1
  84. data/reference/RotFlip_8hpp.html +1 -1
  85. data/reference/Sockets_8hpp-source.html +1 -1
  86. data/reference/Sockets_8hpp.html +1 -1
  87. data/reference/TextInput_8hpp-source.html +1 -1
  88. data/reference/TextInput_8hpp.html +1 -1
  89. data/reference/Text_8hpp-source.html +28 -27
  90. data/reference/Text_8hpp.html +1 -1
  91. data/reference/Timing_8hpp-source.html +1 -1
  92. data/reference/Timing_8hpp.html +1 -1
  93. data/reference/Utility_8hpp-source.html +1 -1
  94. data/reference/Utility_8hpp.html +1 -1
  95. data/reference/WinUtility_8hpp-source.html +1 -1
  96. data/reference/WinUtility_8hpp.html +1 -1
  97. data/reference/Window_8hpp-source.html +76 -68
  98. data/reference/Window_8hpp.html +1 -1
  99. data/reference/annotated.html +1 -1
  100. data/reference/classGosu_1_1Audio-members.html +1 -1
  101. data/reference/classGosu_1_1Audio.html +1 -1
  102. data/reference/classGosu_1_1Bitmap-members.html +3 -2
  103. data/reference/classGosu_1_1Bitmap.html +9 -6
  104. data/reference/classGosu_1_1Buffer-members.html +1 -1
  105. data/reference/classGosu_1_1Buffer.html +1 -1
  106. data/reference/classGosu_1_1Button-members.html +1 -1
  107. data/reference/classGosu_1_1Button.html +2 -2
  108. data/reference/classGosu_1_1Color-members.html +1 -1
  109. data/reference/classGosu_1_1Color.html +1 -1
  110. data/reference/classGosu_1_1File-members.html +1 -1
  111. data/reference/classGosu_1_1File.html +1 -1
  112. data/reference/classGosu_1_1Font-members.html +1 -1
  113. data/reference/classGosu_1_1Font.html +1 -1
  114. data/reference/classGosu_1_1Graphics-members.html +1 -1
  115. data/reference/classGosu_1_1Graphics.html +1 -1
  116. data/reference/classGosu_1_1Image-members.html +1 -1
  117. data/reference/classGosu_1_1Image.html +1 -1
  118. data/reference/classGosu_1_1ImageData-members.html +1 -1
  119. data/reference/classGosu_1_1ImageData.html +1 -1
  120. data/reference/classGosu_1_1Input-members.html +1 -1
  121. data/reference/classGosu_1_1Input.html +1 -1
  122. data/reference/classGosu_1_1MessageSocket-members.html +1 -1
  123. data/reference/classGosu_1_1MessageSocket.html +1 -1
  124. data/reference/classGosu_1_1Resource-members.html +1 -1
  125. data/reference/classGosu_1_1Resource.html +1 -1
  126. data/reference/classGosu_1_1Sample-members.html +1 -1
  127. data/reference/classGosu_1_1Sample.html +1 -1
  128. data/reference/classGosu_1_1SampleInstance-members.html +1 -1
  129. data/reference/classGosu_1_1SampleInstance.html +1 -1
  130. data/reference/classGosu_1_1Song-members.html +1 -1
  131. data/reference/classGosu_1_1Song.html +1 -1
  132. data/reference/classGosu_1_1TextInput-members.html +1 -1
  133. data/reference/classGosu_1_1TextInput.html +1 -1
  134. data/reference/classGosu_1_1Window-members.html +3 -3
  135. data/reference/classGosu_1_1Window.html +27 -9
  136. data/reference/files.html +1 -1
  137. data/reference/functions.html +10 -5
  138. data/reference/functions_enum.html +1 -1
  139. data/reference/functions_func.html +10 -5
  140. data/reference/functions_vars.html +1 -1
  141. data/reference/hierarchy.html +1 -1
  142. data/reference/index.html +1 -1
  143. data/reference/namespaceGosu.html +13 -2
  144. data/reference/namespaceGosu_1_1Colors.html +1 -1
  145. data/reference/namespaceGosu_1_1Win.html +1 -1
  146. data/reference/namespacemembers.html +1 -1
  147. data/reference/namespacemembers_enum.html +1 -1
  148. data/reference/namespacemembers_eval.html +1 -1
  149. data/reference/namespacemembers_func.html +1 -1
  150. data/reference/namespacemembers_type.html +1 -1
  151. data/reference/namespacemembers_vars.html +1 -1
  152. data/reference/namespaces.html +1 -1
  153. data/windows/Gosu.sln +2 -2
  154. data/windows/Gosu.vcproj +7 -8
  155. data/windows/RubyGosu.vcproj +5 -5
  156. 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->physWidth = pimpl->virtWidth = physWidth;
34
- pimpl->physHeight = pimpl->virtHeight = physHeight;
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->virtWidth, pimpl->virtHeight, 0, -1, 1);
42
+ glOrthof(0, pimpl->physWidth, pimpl->physHeight, 0, -1, 1);
43
43
  #else
44
- glOrtho(0, pimpl->virtWidth, pimpl->virtHeight, 0, -1, 1);
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
- /*if ((borderFlags & bfHard) == bfHard &&
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;
@@ -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 - (words - 1) * spaceWidth;
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 - (words - 1) * spaceWidth;
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
- pos += cur->width + spacing;
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
- boost::char_separator<wchar_t> sep(L" ");
185
- Tokenizer words(paragraph, sep);
186
- for (Tokenizer::iterator i = words.begin(); i != words.end(); ++i)
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
- newWord.text = *i;
190
- newWord.width = builder.textWidth(newWord.text);
191
- collectedWords.push_back(newWord);
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
- checkErr( ATSFontActivateFromMemory(buf.data(), buf.size(),
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
- checkErr( ATSFontFindFromContainer(container, kATSOptionFlagsDefault,
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
- checkErr(ATSFontGetHorizontalMetrics(newFont.fontId, kATSOptionFlagsDefault, &metrics));
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
- checkErr( ATSUSetAttributes(style, 1, &tag, &size, &ptr) );
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
- checkErr( ATSUSetLayoutControls(layout, 1, &tag, &size, &ptr) );
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
- checkErr( ATSUCreateStyle(&style) );
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
- checkErr( ATSUCreateTextLayoutWithTextPtr(&utf16[0], kATSUFromTextBeginning,
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
- checkErr( ATSUDisposeStyle(style) );
175
- checkErr( ATSUDisposeTextLayout(layout) );
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
- checkErr( ATSUSetTransientFontMatching(layout, TRUE) );
182
- checkErr( ATSUMeasureTextImage(layout, kATSUFromTextBeginning,
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
- checkErr( ATSUSetTransientFontMatching(layout, TRUE) );
196
- checkErr( ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, x, y) );
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
+ }