gosu 0.7.20 → 0.7.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,248 @@
1
+ #ifndef GOSUIMPL_GRAPHICS_TEXTFORMATTING
2
+ #define GOSUIMPL_GRAPHICS_TEXTFORMATTING
3
+
4
+ #include <Gosu/Color.hpp>
5
+ #include <Gosu/Utility.hpp>
6
+ #include <boost/cstdint.hpp>
7
+ #include <boost/foreach.hpp>
8
+ #include <stdexcept>
9
+ #include <vector>
10
+ #include <cwchar>
11
+
12
+ namespace Gosu
13
+ {
14
+ class FormattedString
15
+ {
16
+ struct FormattedChar
17
+ {
18
+ wchar_t wc;
19
+ Gosu::Color color;
20
+ unsigned flags;
21
+ std::wstring entity;
22
+
23
+ bool sameStyleAs(const FormattedChar& other) const
24
+ {
25
+ return wc && other.wc && color == other.color && flags == other.flags;
26
+ }
27
+ };
28
+ std::vector<FormattedChar> chars;
29
+
30
+ static unsigned flags(int b, int u, int i)
31
+ {
32
+ unsigned flags = 0;
33
+ if (b > 0) flags |= ffBold;
34
+ if (u > 0) flags |= ffUnderline;
35
+ if (i > 0) flags |= ffItalic;
36
+ return flags;
37
+ }
38
+
39
+ public:
40
+ FormattedString()
41
+ {
42
+ }
43
+
44
+ explicit FormattedString(const std::wstring& html, unsigned baseFlags)
45
+ {
46
+ unsigned pos = 0;
47
+ int b = (baseFlags & ffBold) ? 1 : 0,
48
+ u = (baseFlags & ffUnderline) ? 1 : 0,
49
+ i = (baseFlags & ffItalic) ? 1 : 0;
50
+ std::vector<Gosu::Color> c;
51
+ c.push_back(0xffffffff);
52
+ while (pos < html.length())
53
+ {
54
+ // TODO: range checking for the color ops so .at() doesn't crash valid strings
55
+
56
+ if (html.substr(pos, 3) == L"<b>")
57
+ {
58
+ b += 1;
59
+ pos += 3;
60
+ continue;
61
+ }
62
+ if (html.substr(pos, 4) == L"</b>")
63
+ {
64
+ b -= 1;
65
+ pos += 4;
66
+ continue;
67
+ }
68
+ if (html.substr(pos, 3) == L"<u>")
69
+ {
70
+ u += 1;
71
+ pos += 3;
72
+ continue;
73
+ }
74
+ if (html.substr(pos, 4) == L"</u>")
75
+ {
76
+ u -= 1;
77
+ pos += 4;
78
+ continue;
79
+ }
80
+ if (html.substr(pos, 3) == L"<i>")
81
+ {
82
+ i += 1;
83
+ pos += 3;
84
+ continue;
85
+ }
86
+ if (html.substr(pos, 4) == L"</i>")
87
+ {
88
+ i -= 1;
89
+ pos += 4;
90
+ continue;
91
+ }
92
+ if (html.substr(pos, 3) == L"<c=" &&
93
+ html.at(pos + 9) == L'>')
94
+ {
95
+ using namespace std;
96
+ boost::uint32_t rgb =
97
+ std::wcstoul(html.c_str() + pos + 3, 0, 16);
98
+ c.push_back(0xff000000 | rgb);
99
+ pos += 10;
100
+ continue;
101
+ }
102
+ if (html.substr(pos, 3) == L"<c=" &&
103
+ html.at(pos + 11) == L'>')
104
+ {
105
+ using namespace std;
106
+ boost::uint32_t argb =
107
+ std::wcstoul(html.c_str() + pos + 3, 0, 16);
108
+ c.push_back(argb);
109
+ pos += 12;
110
+ continue;
111
+ }
112
+ if (html.substr(pos, 4) == L"</c>")
113
+ {
114
+ c.pop_back();
115
+ pos += 4;
116
+ continue;
117
+ }
118
+ if (html.substr(pos, 4) == L"&lt;")
119
+ {
120
+ FormattedChar fc = { L'<', c.back(), flags(b,u,i) };
121
+ chars.push_back(fc);
122
+ pos += 4;
123
+ continue;
124
+ }
125
+ if (html.substr(pos, 4) == L"&gt;")
126
+ {
127
+ FormattedChar fc = { L'>', c.back(), flags(b,u,i) };
128
+ chars.push_back(fc);
129
+ pos += 4;
130
+ continue;
131
+ }
132
+ if (html.substr(pos, 5) == L"&amp;")
133
+ {
134
+ FormattedChar fc = { L'&', c.back(), flags(b,u,i) };
135
+ chars.push_back(fc);
136
+ pos += 5;
137
+ continue;
138
+ }
139
+ if (html[pos] == L'&' && pos < html.length() - 1)
140
+ {
141
+ int endOfEntity = pos + 1;
142
+ while (html[endOfEntity] != L';')
143
+ {
144
+ using namespace std; // never know where the wchar_t stuff is ...
145
+ if (!iswalnum(static_cast<wint_t>(html[endOfEntity])))
146
+ goto normalCharacter;
147
+ endOfEntity += 1;
148
+ if (endOfEntity >= html.size())
149
+ goto normalCharacter;
150
+ }
151
+ FormattedChar fc = { 0, c.back(), 0, std::wstring(html.begin() + pos + 1, html.begin() + endOfEntity) };
152
+ chars.push_back(fc);
153
+ pos = endOfEntity + 1;
154
+ continue;
155
+ }
156
+
157
+ normalCharacter:
158
+ FormattedChar fc = { html[pos], c.back(), flags(b,u,i) };
159
+ chars.push_back(fc);
160
+ pos += 1;
161
+ }
162
+ }
163
+
164
+ std::wstring unformat() const
165
+ {
166
+ std::wstring result(length(), L' ');
167
+ for (int i = 0; i < chars.size(); ++i)
168
+ result[i] = chars[i].wc;
169
+ return result;
170
+ }
171
+
172
+ const wchar_t* entityAt(unsigned index) const
173
+ {
174
+ if (chars[index].wc != 0 || chars[index].entity.empty())
175
+ return 0;
176
+ return chars[index].entity.c_str();
177
+ }
178
+
179
+ wchar_t charAt(unsigned index) const
180
+ {
181
+ return chars[index].wc;
182
+ }
183
+
184
+ unsigned flagsAt(unsigned index) const
185
+ {
186
+ return chars[index].flags;
187
+ }
188
+
189
+ Gosu::Color colorAt(unsigned index) const
190
+ {
191
+ return chars[index].color;
192
+ }
193
+
194
+ unsigned length() const
195
+ {
196
+ return chars.size();
197
+ }
198
+
199
+ FormattedString range(unsigned begin, unsigned end) const
200
+ {
201
+ FormattedString result;
202
+ result.chars.assign(chars.begin() + begin, chars.begin() + end);
203
+ return result;
204
+ }
205
+
206
+ std::vector<FormattedString> splitLines() const
207
+ {
208
+ std::vector<FormattedString> result;
209
+ unsigned begin = 0;
210
+ for (unsigned cur = 0; cur < length(); ++cur)
211
+ {
212
+ if (charAt(cur) == L'\n')
213
+ {
214
+ FormattedString line;
215
+ line.chars.assign(chars.begin() + begin, chars.begin() + cur);
216
+ result.push_back(line);
217
+ begin = cur + 1;
218
+ }
219
+ }
220
+ FormattedString line;
221
+ line.chars.assign(chars.begin() + begin, chars.end());
222
+ result.push_back(line);
223
+ return result;
224
+ }
225
+
226
+ std::vector<FormattedString> splitParts() const
227
+ {
228
+ std::vector<FormattedString> result;
229
+ unsigned begin = 0;
230
+ for (unsigned cur = 1; cur < length(); ++cur)
231
+ {
232
+ if (!chars[begin].sameStyleAs(chars[cur]))
233
+ {
234
+ FormattedString line;
235
+ line.chars.assign(chars.begin() + begin, chars.begin() + cur);
236
+ result.push_back(line);
237
+ begin = cur;
238
+ }
239
+ }
240
+ FormattedString line;
241
+ line.chars.assign(chars.begin() + begin, chars.end());
242
+ result.push_back(line);
243
+ return result;
244
+ }
245
+ };
246
+ }
247
+
248
+ #endif
@@ -6,6 +6,8 @@
6
6
  #include <GosuImpl/Graphics/LargeImageData.hpp>
7
7
  #include <GosuImpl/Graphics/Macro.hpp>
8
8
  #include <Gosu/Bitmap.hpp>
9
+ #include <Gosu/Image.hpp>
10
+ #include <boost/foreach.hpp>
9
11
  #if 0
10
12
  #include <boost/thread.hpp>
11
13
  #endif
@@ -22,10 +24,20 @@ struct Gosu::Graphics::Impl
22
24
  DrawOpQueueStack queues;
23
25
  typedef std::vector<boost::shared_ptr<Texture> > Textures;
24
26
  Textures textures;
27
+ Transforms currentTransforms;
28
+ Transforms absoluteTransforms;
25
29
 
26
30
  #if 0
27
31
  boost::mutex texMutex;
28
32
  #endif
33
+
34
+ void calculateAbsoluteTransform()
35
+ {
36
+ Transform result = scale(1);
37
+ BOOST_FOREACH (const Transform& tf, currentTransforms)
38
+ result = multiply(result, tf);
39
+ absoluteTransforms.push_back(result);
40
+ }
29
41
  };
30
42
 
31
43
  Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscreen)
@@ -57,6 +69,9 @@ Gosu::Graphics::Graphics(unsigned physWidth, unsigned physHeight, bool fullscree
57
69
 
58
70
  // Create default draw-op queue.
59
71
  pimpl->queues.resize(1);
72
+
73
+ // Push one identity matrix as the default transform.
74
+ pimpl->absoluteTransforms.push_back(scale(1));
60
75
  }
61
76
 
62
77
  Gosu::Graphics::~Graphics()
@@ -107,7 +122,12 @@ void Gosu::Graphics::setResolution(unsigned virtualWidth, unsigned virtualHeight
107
122
  bool Gosu::Graphics::begin(Gosu::Color clearWithColor)
108
123
  {
109
124
  // If there is a recording in process, stop it.
125
+ // TODO: Raise exception?
110
126
  pimpl->queues.resize(1);
127
+
128
+ // If there are transformations in progress, clear them.
129
+ pimpl->currentTransforms.resize(0);
130
+ pimpl->absoluteTransforms.resize(1);
111
131
 
112
132
  // Flush leftover clippings
113
133
  endClipping();
@@ -229,11 +249,23 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::endRecording()
229
249
  return result;
230
250
  }
231
251
 
252
+ void Gosu::Graphics::pushTransform(const Gosu::Transform& transform)
253
+ {
254
+ pimpl->currentTransforms.push_back(transform);
255
+ pimpl->calculateAbsoluteTransform();
256
+ }
257
+
258
+ void Gosu::Graphics::popTransform()
259
+ {
260
+ pimpl->currentTransforms.pop_back();
261
+ pimpl->calculateAbsoluteTransform();
262
+ }
263
+
232
264
  void Gosu::Graphics::drawLine(double x1, double y1, Color c1,
233
265
  double x2, double y2, Color c2,
234
266
  ZPos z, AlphaMode mode)
235
267
  {
236
- DrawOp op;
268
+ DrawOp op(pimpl->absoluteTransforms.back());
237
269
 
238
270
  x1 *= factorX();
239
271
  y1 *= factorY();
@@ -253,7 +285,7 @@ void Gosu::Graphics::drawTriangle(double x1, double y1, Color c1,
253
285
  double x3, double y3, Color c3,
254
286
  ZPos z, AlphaMode mode)
255
287
  {
256
- DrawOp op;
288
+ DrawOp op(pimpl->absoluteTransforms.back());
257
289
 
258
290
  x1 *= factorX();
259
291
  y1 *= factorY();
@@ -283,7 +315,7 @@ void Gosu::Graphics::drawQuad(double x1, double y1, Color c1,
283
315
  {
284
316
  reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
285
317
 
286
- DrawOp op;
318
+ DrawOp op(pimpl->absoluteTransforms.back());
287
319
 
288
320
  x1 *= factorX();
289
321
  y1 *= factorY();
@@ -332,7 +364,7 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
332
364
  if (srcX == 0 && srcWidth == src.width() &&
333
365
  srcY == 0 && srcHeight == src.height())
334
366
  {
335
- data = texture->tryAlloc(*this, pimpl->queues, texture,
367
+ data = texture->tryAlloc(*this, pimpl->absoluteTransforms, pimpl->queues, texture,
336
368
  src, 0, 0, src.width(), src.height(), 0);
337
369
  }
338
370
  else
@@ -340,7 +372,7 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
340
372
  Bitmap trimmedSrc;
341
373
  trimmedSrc.resize(srcWidth, srcHeight);
342
374
  trimmedSrc.insert(src, 0, 0, srcX, srcY, srcWidth, srcHeight);
343
- data = texture->tryAlloc(*this, pimpl->queues, texture,
375
+ data = texture->tryAlloc(*this, pimpl->absoluteTransforms, pimpl->queues, texture,
344
376
  trimmedSrc, 0, 0, trimmedSrc.width(), trimmedSrc.height(), 0);
345
377
  }
346
378
 
@@ -373,7 +405,7 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
373
405
  boost::shared_ptr<Texture> texture(*i);
374
406
 
375
407
  std::auto_ptr<ImageData> data;
376
- data = texture->tryAlloc(*this, pimpl->queues, texture, bmp, 0, 0, bmp.width(), bmp.height(), 1);
408
+ data = texture->tryAlloc(*this, pimpl->absoluteTransforms, pimpl->queues, texture, bmp, 0, 0, bmp.width(), bmp.height(), 1);
377
409
  if (data.get())
378
410
  return data;
379
411
  }
@@ -385,7 +417,7 @@ std::auto_ptr<Gosu::ImageData> Gosu::Graphics::createImage(
385
417
  pimpl->textures.push_back(texture);
386
418
 
387
419
  std::auto_ptr<ImageData> data;
388
- data = texture->tryAlloc(*this, pimpl->queues, texture, bmp, 0, 0, bmp.width(), bmp.height(), 1);
420
+ data = texture->tryAlloc(*this, pimpl->absoluteTransforms, pimpl->queues, texture, bmp, 0, 0, bmp.width(), bmp.height(), 1);
389
421
  if (!data.get())
390
422
  throw std::logic_error("Internal texture block allocation error");
391
423
 
@@ -116,3 +116,13 @@ void Gosu::LargeImageData::draw(double x1, double y1, Color c1,
116
116
  absXBL, absYBL, absCBL, absXBR, absYBR, absCBR, z, mode);
117
117
  }
118
118
  }
119
+
120
+ Gosu::Bitmap Gosu::LargeImageData::toBitmap() const
121
+ {
122
+ Bitmap bitmap;
123
+ bitmap.resize(width(), height());
124
+ for (int x = 0; x < partsX; ++x)
125
+ for (int y = 0; y < partsY; ++y)
126
+ bitmap.insert(parts[y * partsX + x]->toBitmap(), x * partWidth, y * partHeight);
127
+ return bitmap;
128
+ }
@@ -31,6 +31,8 @@ namespace Gosu
31
31
  {
32
32
  return boost::none;
33
33
  }
34
+
35
+ Bitmap toBitmap() const;
34
36
  };
35
37
  }
36
38
 
@@ -73,6 +73,11 @@ public:
73
73
  {
74
74
  return boost::none;
75
75
  }
76
+
77
+ Gosu::Bitmap toBitmap() const
78
+ {
79
+ throw std::logic_error("Gosu::Macro cannot be rendered to Gosu::Bitmap");
80
+ }
76
81
  };
77
82
 
78
83
  #endif
@@ -4,10 +4,10 @@
4
4
  #include <Gosu/Bitmap.hpp>
5
5
  #include <Gosu/Graphics.hpp>
6
6
 
7
- Gosu::TexChunk::TexChunk(Graphics& graphics, DrawOpQueueStack& queues,
8
- boost::shared_ptr<Texture> texture,
9
- int x, int y, int w, int h, int padding)
10
- : graphics(&graphics), queues(&queues), texture(texture), x(x), y(y), w(w), h(h), padding(padding)
7
+ Gosu::TexChunk::TexChunk(Graphics& graphics, Transforms& transforms, DrawOpQueueStack& queues,
8
+ boost::shared_ptr<Texture> texture, int x, int y, int w, int h, int padding)
9
+ : graphics(&graphics), transforms(&transforms), queues(&queues),
10
+ texture(texture), x(x), y(y), w(w), h(h), padding(padding)
11
11
  {
12
12
  }
13
13
 
@@ -45,7 +45,7 @@ void Gosu::TexChunk::draw(double x1, double y1, Color c1,
45
45
  double x4, double y4, Color c4,
46
46
  ZPos z, AlphaMode mode) const
47
47
  {
48
- DrawOp newDrawOp;
48
+ DrawOp newDrawOp(transforms->back());
49
49
 
50
50
  reorderCoordinatesIfNecessary(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
51
51
 
@@ -82,3 +82,8 @@ boost::optional<Gosu::GLTexInfo> Gosu::TexChunk::glTexInfo() const
82
82
  getCoords(info.left, info.top, info.right, info.bottom);
83
83
  return info;
84
84
  }
85
+
86
+ Gosu::Bitmap Gosu::TexChunk::toBitmap() const
87
+ {
88
+ return texture->toBitmap(x, y, w, h);
89
+ }
@@ -12,13 +12,14 @@
12
12
  class Gosu::TexChunk : public Gosu::ImageData
13
13
  {
14
14
  Graphics* graphics;
15
+ Transforms* transforms;
15
16
  DrawOpQueueStack* queues;
16
17
  boost::shared_ptr<Texture> texture;
17
18
  int x, y, w, h, padding;
18
19
 
19
20
  public:
20
- TexChunk(Graphics& graphics, DrawOpQueueStack& queues, boost::shared_ptr<Texture> texture,
21
- int x, int y, int w, int h, int padding);
21
+ TexChunk(Graphics& graphics, Transforms& transforms, DrawOpQueueStack& queues,
22
+ boost::shared_ptr<Texture> texture, int x, int y, int w, int h, int padding);
22
23
  ~TexChunk();
23
24
 
24
25
  unsigned int width() const;
@@ -34,6 +35,7 @@ public:
34
35
  ZPos z, AlphaMode mode) const;
35
36
 
36
37
  boost::optional<GLTexInfo> glTexInfo() const;
38
+ Gosu::Bitmap toBitmap() const;
37
39
  };
38
40
 
39
41
  #endif