gosu 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gosu/Bitmap.hpp +3 -3
- data/Gosu/Directories.hpp +6 -3
- data/Gosu/Gosu.hpp +0 -1
- data/Gosu/GraphicsBase.hpp +12 -8
- data/Gosu/Input.hpp +5 -16
- data/Gosu/Platform.hpp +1 -0
- data/Gosu/Version.hpp +3 -5
- data/Gosu/Window.hpp +7 -8
- data/README.txt +3 -3
- data/ext/gosu/extconf.rb +17 -16
- data/ext/gosu/gosu_wrap.cxx +59 -58
- data/ext/gosu/gosu_wrap.h +1 -1
- data/rdoc/gosu.rb +285 -283
- data/src/{MacUtility.hpp → AppleUtility.hpp} +24 -42
- data/src/Audio/ALChannelManagement.hpp +1 -1
- data/src/Audio/{AudioOpenAL.cpp → Audio.cpp} +6 -7
- data/src/Audio/Audio.mm +1 -0
- data/src/Audio/AudioFile.hpp +2 -2
- data/src/Audio/AudioToolboxFile.hpp +5 -20
- data/src/Audio/OggFile.hpp +44 -56
- data/src/Audio/SndFile.hpp +2 -2
- data/src/Bitmap/Bitmap.cpp +98 -2
- data/src/Bitmap/BitmapIO.cpp +156 -0
- data/src/DirectoriesApple.mm +76 -0
- data/src/DirectoriesUnix.cpp +5 -12
- data/src/DirectoriesWin.cpp +5 -0
- data/src/Graphics/BlockAllocator.hpp +2 -2
- data/src/Graphics/ClipRectStack.hpp +2 -2
- data/src/Graphics/Common.hpp +2 -2
- data/src/Graphics/DrawOp.hpp +2 -2
- data/src/Graphics/DrawOpQueue.hpp +2 -2
- data/src/Graphics/Graphics.cpp +7 -2
- data/src/Graphics/LargeImageData.cpp +6 -6
- data/src/Graphics/LargeImageData.hpp +3 -3
- data/src/Graphics/Macro.hpp +2 -2
- data/src/Graphics/RenderState.hpp +2 -2
- data/src/Graphics/Resolution.cpp +1 -1
- data/src/Graphics/TexChunk.hpp +2 -2
- data/src/Graphics/Texture.cpp +21 -16
- data/src/Graphics/Texture.hpp +7 -5
- data/src/Graphics/TransformStack.hpp +2 -2
- data/src/Iconv.hpp +2 -2
- data/src/Input/Input.cpp +3 -1
- data/src/Input/{InputTouch.mm → InputUIKit.mm} +32 -26
- data/src/Input/TextInput.cpp +1 -1
- data/src/Text/FormattedString.hpp +2 -2
- data/src/Text/TextApple.mm +8 -8
- data/src/Text/TextMac.cpp +1 -1
- data/src/Text/TextUnix.cpp +1 -1
- data/src/UIKit/GosuAppDelegate.h +8 -0
- data/src/UIKit/GosuAppDelegate.mm +24 -0
- data/src/UIKit/GosuGLView.h +8 -0
- data/src/UIKit/GosuGLView.mm +130 -0
- data/src/UIKit/GosuViewController.h +13 -0
- data/src/UIKit/GosuViewController.mm +214 -0
- data/src/UtilityApple.mm +5 -18
- data/src/Window.cpp +1 -3
- data/src/WindowUIKit.mm +124 -0
- data/src/stb_image.h +6437 -0
- data/src/stb_image_write.h +730 -0
- data/src/stb_vorbis.c +5459 -0
- metadata +18 -26
- data/Gosu/Sockets.hpp +0 -156
- data/src/Audio/AudioOpenAL.mm +0 -1
- data/src/Bitmap/BitmapApple.mm +0 -226
- data/src/Bitmap/BitmapBMP.cpp +0 -79
- data/src/Bitmap/BitmapColorKey.cpp +0 -50
- data/src/Bitmap/BitmapFreeImage.cpp +0 -174
- data/src/Bitmap/BitmapGDIplus.cpp +0 -212
- data/src/Bitmap/BitmapUtils.cpp +0 -76
- data/src/DirectoriesMac.mm +0 -38
- data/src/DirectoriesTouch.mm +0 -38
- data/src/GosuView.hpp +0 -15
- data/src/GosuView.mm +0 -208
- data/src/Input/AccelerometerReader.hpp +0 -10
- data/src/Input/AccelerometerReader.mm +0 -31
- data/src/Sockets/CommSocket.cpp +0 -305
- data/src/Sockets/ListenerSocket.cpp +0 -59
- data/src/Sockets/MessageSocket.cpp +0 -128
- data/src/Sockets/Socket.cpp +0 -145
- data/src/Sockets/Socket.hpp +0 -66
- data/src/WindowTouch.mm +0 -243
- data/src/X11vroot.h +0 -118
data/src/Bitmap/BitmapBMP.cpp
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
#include <Gosu/Platform.hpp>
|
2
|
-
|
3
|
-
// All other platforms use OS libraries instead.
|
4
|
-
#ifdef GOSU_IS_IPHONE
|
5
|
-
#include <Gosu/Bitmap.hpp>
|
6
|
-
#include <Gosu/IO.hpp>
|
7
|
-
#include <Gosu/TR1.hpp>
|
8
|
-
|
9
|
-
namespace
|
10
|
-
{
|
11
|
-
template<unsigned bits> struct UintSelector;
|
12
|
-
template<> struct UintSelector<8> { typedef std::tr1::uint8_t Type; };
|
13
|
-
template<> struct UintSelector<16> { typedef std::tr1::uint16_t Type; };
|
14
|
-
template<> struct UintSelector<32> { typedef std::tr1::uint32_t Type; };
|
15
|
-
|
16
|
-
template<unsigned bits, typename T>
|
17
|
-
void writeVal(Gosu::Writer& writer, T value)
|
18
|
-
{
|
19
|
-
typename UintSelector<bits>::Type val = value;
|
20
|
-
writer.writePod(val, Gosu::boLittle);
|
21
|
-
}
|
22
|
-
}
|
23
|
-
|
24
|
-
Gosu::Writer Gosu::saveToBMP(const Bitmap& bmp, Writer writer)
|
25
|
-
{
|
26
|
-
// rowSize is the width ceiled to the next multiple of four.
|
27
|
-
unsigned rowSize = bmp.width() * 3;
|
28
|
-
rowSize = int((float(rowSize) - 1.0)/4.0 + 1.0) * 4;
|
29
|
-
|
30
|
-
// File header
|
31
|
-
// Type
|
32
|
-
writeVal<8>(writer, 'B');
|
33
|
-
writeVal<8>(writer, 'M');
|
34
|
-
// Size
|
35
|
-
writeVal<32>(writer, 14 + 40 + rowSize * bmp.height());
|
36
|
-
// Reserved
|
37
|
-
writeVal<16>(writer, 0);
|
38
|
-
writeVal<16>(writer, 0);
|
39
|
-
// Offset to data
|
40
|
-
writeVal<32>(writer, 14 + 40);
|
41
|
-
|
42
|
-
// Info header
|
43
|
-
// Size
|
44
|
-
writeVal<32>(writer, 40);
|
45
|
-
// Width, height
|
46
|
-
writeVal<32>(writer, bmp.width());
|
47
|
-
writeVal<32>(writer, bmp.height());
|
48
|
-
// Planes
|
49
|
-
writeVal<16>(writer, 1);
|
50
|
-
// Bit count
|
51
|
-
writeVal<16>(writer, 24);
|
52
|
-
// Compression
|
53
|
-
writeVal<32>(writer, 0);
|
54
|
-
// Image size
|
55
|
-
writeVal<32>(writer, rowSize * bmp.height());
|
56
|
-
// xPelsPerMeter/yPelsPerMeter
|
57
|
-
writeVal<32>(writer, 0);
|
58
|
-
writeVal<32>(writer, 0);
|
59
|
-
// Used and important colors
|
60
|
-
writeVal<32>(writer, 0);
|
61
|
-
writeVal<32>(writer, 0);
|
62
|
-
|
63
|
-
for (int y = bmp.height() - 1; y >= 0; y--)
|
64
|
-
{
|
65
|
-
for (unsigned x = 0; x < bmp.width(); x++)
|
66
|
-
{
|
67
|
-
// BGR order
|
68
|
-
writeVal<8>(writer, bmp.getPixel(x, y).blue());
|
69
|
-
writeVal<8>(writer, bmp.getPixel(x, y).green());
|
70
|
-
writeVal<8>(writer, bmp.getPixel(x, y).red());
|
71
|
-
}
|
72
|
-
int offset = rowSize - bmp.width() * 3;
|
73
|
-
for(int i = 0; i < offset; ++i)
|
74
|
-
writeVal<8>(writer, 0);
|
75
|
-
}
|
76
|
-
return writer;
|
77
|
-
}
|
78
|
-
|
79
|
-
#endif
|
@@ -1,50 +0,0 @@
|
|
1
|
-
#include <Gosu/Bitmap.hpp>
|
2
|
-
#include <vector>
|
3
|
-
|
4
|
-
void Gosu::applyColorKey(Bitmap& bitmap, Color key)
|
5
|
-
{
|
6
|
-
std::vector<Color> surroundingColors;
|
7
|
-
surroundingColors.reserve(4);
|
8
|
-
|
9
|
-
for (unsigned y = 0; y < bitmap.height(); ++y)
|
10
|
-
for (unsigned x = 0; x < bitmap.width(); ++x)
|
11
|
-
if (bitmap.getPixel(x, y) == key)
|
12
|
-
{
|
13
|
-
surroundingColors.clear();
|
14
|
-
if (x > 0 && bitmap.getPixel(x - 1, y) != key)
|
15
|
-
surroundingColors.push_back(bitmap.getPixel(x - 1, y));
|
16
|
-
if (x < bitmap.width() - 1 && bitmap.getPixel(x + 1, y) != key)
|
17
|
-
surroundingColors.push_back(bitmap.getPixel(x + 1, y));
|
18
|
-
if (y > 0 && bitmap.getPixel(x, y - 1) != key)
|
19
|
-
surroundingColors.push_back(bitmap.getPixel(x, y - 1));
|
20
|
-
if (y < bitmap.height() - 1 && bitmap.getPixel(x, y + 1) != key)
|
21
|
-
surroundingColors.push_back(bitmap.getPixel(x, y + 1));
|
22
|
-
|
23
|
-
if (surroundingColors.empty())
|
24
|
-
{
|
25
|
-
bitmap.setPixel(x, y, Color::NONE);
|
26
|
-
continue;
|
27
|
-
}
|
28
|
-
|
29
|
-
unsigned red = 0, green = 0, blue = 0;
|
30
|
-
for (unsigned i = 0; i < surroundingColors.size(); ++i)
|
31
|
-
{
|
32
|
-
red += surroundingColors[i].red();
|
33
|
-
green += surroundingColors[i].green();
|
34
|
-
blue += surroundingColors[i].blue();
|
35
|
-
}
|
36
|
-
bitmap.setPixel(x, y, Color(0, red / surroundingColors.size(),
|
37
|
-
green / surroundingColors.size(), blue / surroundingColors.size()));
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
|
-
void Gosu::unapplyColorKey(Bitmap& bitmap, Color color)
|
42
|
-
{
|
43
|
-
Color* p = bitmap.data();
|
44
|
-
for (int i = bitmap.width() * bitmap.height(); i > 0; --i, ++p)
|
45
|
-
if (p->alpha() == 0)
|
46
|
-
*p = color;
|
47
|
-
else
|
48
|
-
p->setAlpha(255);
|
49
|
-
}
|
50
|
-
|
@@ -1,174 +0,0 @@
|
|
1
|
-
#include <Gosu/Bitmap.hpp>
|
2
|
-
#include <Gosu/IO.hpp>
|
3
|
-
#include <Gosu/Platform.hpp>
|
4
|
-
#include <Gosu/TR1.hpp>
|
5
|
-
#include <Gosu/Utility.hpp>
|
6
|
-
#include <stdexcept>
|
7
|
-
#include <vector>
|
8
|
-
#include <FreeImage.h>
|
9
|
-
|
10
|
-
// Compatibility with FreeImage <3.1.3. Subtly changes Gosu's behavior though.
|
11
|
-
#ifndef JPEG_EXIFROTATE
|
12
|
-
#define JPEG_EXIFROTATE 0
|
13
|
-
#endif
|
14
|
-
|
15
|
-
// With MSVC, add a suffix so FreeImage can be linked as a fallback for GDI+.
|
16
|
-
// With MinGW, Gosu uses FreeImage all the time, so no suffix is needed.
|
17
|
-
#ifdef _MSC_VER
|
18
|
-
#define FI(x) x##_FreeImage
|
19
|
-
#else
|
20
|
-
#define FI(x) x
|
21
|
-
#endif
|
22
|
-
|
23
|
-
namespace
|
24
|
-
{
|
25
|
-
const int GOSU_FIFLAGS = (JPEG_EXIFROTATE | ICO_MAKEALPHA | PNG_IGNOREGAMMA);
|
26
|
-
|
27
|
-
void reshuffleBitmap(Gosu::Bitmap& bitmap)
|
28
|
-
{
|
29
|
-
// Since FreeImage gracefully ignores the MASK parameters above, we
|
30
|
-
// manually exchange the R and B channels.
|
31
|
-
std::tr1::uint32_t* p = reinterpret_cast<std::tr1::uint32_t*>(bitmap.data());
|
32
|
-
for (int i = bitmap.width() * bitmap.height(); i > 0; --i, ++p)
|
33
|
-
*p = (*p & 0xff00ff00) | ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff);
|
34
|
-
}
|
35
|
-
|
36
|
-
FIBITMAP* ensure32bits(FIBITMAP* fib)
|
37
|
-
{
|
38
|
-
int bpp = FreeImage_GetBPP(fib);
|
39
|
-
FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(fib);
|
40
|
-
if (bpp != 32 && (image_type == FIT_BITMAP || image_type == FIT_RGBA16)) {
|
41
|
-
FIBITMAP* fib32 = FreeImage_ConvertTo32Bits(fib);
|
42
|
-
FreeImage_Unload(fib);
|
43
|
-
fib = fib32;
|
44
|
-
}
|
45
|
-
return fib;
|
46
|
-
}
|
47
|
-
|
48
|
-
void fibToBitmap(Gosu::Bitmap& bitmap, FIBITMAP* fib, FREE_IMAGE_FORMAT fif)
|
49
|
-
{
|
50
|
-
bitmap.resize(FreeImage_GetWidth(fib), FreeImage_GetHeight(fib));
|
51
|
-
fib = ensure32bits(fib);
|
52
|
-
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(bitmap.data()),
|
53
|
-
fib, bitmap.width() * 4, 32,
|
54
|
-
FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, TRUE);
|
55
|
-
FreeImage_Unload(fib);
|
56
|
-
reshuffleBitmap(bitmap);
|
57
|
-
if (fif == FIF_BMP)
|
58
|
-
Gosu::applyColorKey(bitmap, Gosu::Color::FUCHSIA);
|
59
|
-
}
|
60
|
-
|
61
|
-
FIBITMAP* bitmapToFIB(Gosu::Bitmap bitmap, FREE_IMAGE_FORMAT fif)
|
62
|
-
{
|
63
|
-
reshuffleBitmap(bitmap);
|
64
|
-
if (fif == FIF_BMP)
|
65
|
-
unapplyColorKey(bitmap, Gosu::Color::FUCHSIA);
|
66
|
-
return FreeImage_ConvertFromRawBits((BYTE*)bitmap.data(),
|
67
|
-
bitmap.width(), bitmap.height(), bitmap.width() * 4, 32,
|
68
|
-
FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, true);
|
69
|
-
}
|
70
|
-
|
71
|
-
// Wrap Gosu::Writer as a FreeImageIO.
|
72
|
-
unsigned DLL_CALLCONV WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle)
|
73
|
-
{
|
74
|
-
((Gosu::Writer*)handle)->write(buffer, size * count);
|
75
|
-
return count;
|
76
|
-
}
|
77
|
-
int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin)
|
78
|
-
{
|
79
|
-
Gosu::Writer& writer = *(Gosu::Writer*)handle;
|
80
|
-
switch (origin)
|
81
|
-
{
|
82
|
-
case SEEK_SET: writer.setPosition(offset); break;
|
83
|
-
case SEEK_CUR: writer.seek(offset); break;
|
84
|
-
case SEEK_END: writer.setPosition(writer.resource().size() - offset); break;
|
85
|
-
};
|
86
|
-
return 0;
|
87
|
-
}
|
88
|
-
long DLL_CALLCONV TellProc(fi_handle handle)
|
89
|
-
{
|
90
|
-
return ((Gosu::Writer*)handle)->position();
|
91
|
-
}
|
92
|
-
|
93
|
-
// TODO: This is not thread safe!
|
94
|
-
|
95
|
-
std::string lastFreeImageError;
|
96
|
-
|
97
|
-
void DLL_CALLCONV FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message)
|
98
|
-
{
|
99
|
-
lastFreeImageError = (message && message[0]) ? message : "Unknown error";
|
100
|
-
if (fif != FIF_UNKNOWN)
|
101
|
-
if (const char* format = FreeImage_GetFormatFromFIF(fif))
|
102
|
-
lastFreeImageError += std::string(" (in ") + format + " parser)";
|
103
|
-
}
|
104
|
-
|
105
|
-
void checkForFreeImageErrors(bool value = true)
|
106
|
-
{
|
107
|
-
if (!value || !lastFreeImageError.empty())
|
108
|
-
{
|
109
|
-
std::string message = lastFreeImageError;
|
110
|
-
if (message.empty())
|
111
|
-
message = "Unknown error";
|
112
|
-
else
|
113
|
-
lastFreeImageError.clear();
|
114
|
-
throw std::runtime_error(message);
|
115
|
-
}
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
namespace Gosu
|
120
|
-
{
|
121
|
-
void FI(loadImageFile)(Bitmap& bitmap, const std::wstring& filename)
|
122
|
-
{
|
123
|
-
#ifdef GOSU_IS_WIN
|
124
|
-
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeU(filename.c_str());
|
125
|
-
FIBITMAP* fib = FreeImage_LoadU(fif, filename.c_str(), GOSU_FIFLAGS);
|
126
|
-
#else
|
127
|
-
std::string utf8Filename = wstringToUTF8(filename);
|
128
|
-
FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(utf8Filename.c_str());
|
129
|
-
FIBITMAP* fib = FreeImage_Load(fif, utf8Filename.c_str(), GOSU_FIFLAGS);
|
130
|
-
#endif
|
131
|
-
checkForFreeImageErrors(fib != 0);
|
132
|
-
fibToBitmap(bitmap, fib, fif);
|
133
|
-
}
|
134
|
-
|
135
|
-
void FI(loadImageFile)(Bitmap& bitmap, Gosu::Reader input)
|
136
|
-
{
|
137
|
-
// Read all available input
|
138
|
-
std::vector<BYTE> data(input.resource().size() - input.position());
|
139
|
-
input.read(&data[0], data.size());
|
140
|
-
FIMEMORY* fim = FreeImage_OpenMemory(&data[0], data.size());
|
141
|
-
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(fim);
|
142
|
-
FIBITMAP* fib = FreeImage_LoadFromMemory(fif, fim, GOSU_FIFLAGS);
|
143
|
-
checkForFreeImageErrors(fib != 0);
|
144
|
-
fibToBitmap(bitmap, fib, fif);
|
145
|
-
}
|
146
|
-
|
147
|
-
void FI(saveImageFile)(const Bitmap& bitmap, const std::wstring& filename)
|
148
|
-
{
|
149
|
-
std::string utf8Filename = wstringToUTF8(filename);
|
150
|
-
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(utf8Filename.c_str());
|
151
|
-
FIBITMAP* fib = bitmapToFIB(bitmap, fif);
|
152
|
-
|
153
|
-
#ifdef GOSU_IS_WIN
|
154
|
-
FreeImage_SaveU(fif, fib, filename.c_str());
|
155
|
-
#else
|
156
|
-
FreeImage_Save(fif, fib, utf8Filename.c_str());
|
157
|
-
#endif
|
158
|
-
FreeImage_Unload(fib);
|
159
|
-
checkForFreeImageErrors();
|
160
|
-
}
|
161
|
-
|
162
|
-
void FI(saveImageFile)(const Bitmap& bitmap, Gosu::Writer writer,
|
163
|
-
const std::wstring& formatHint)
|
164
|
-
{
|
165
|
-
std::string utf8FormatHint = wstringToUTF8(formatHint);
|
166
|
-
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(utf8FormatHint.c_str());
|
167
|
-
FIBITMAP* fib = bitmapToFIB(bitmap, fif);
|
168
|
-
|
169
|
-
FreeImageIO fio = { NULL, WriteProc, SeekProc, TellProc };
|
170
|
-
FreeImage_SaveToHandle(fif, fib, &fio, &writer);
|
171
|
-
FreeImage_Unload(fib);
|
172
|
-
checkForFreeImageErrors();
|
173
|
-
}
|
174
|
-
}
|
@@ -1,212 +0,0 @@
|
|
1
|
-
#include <Gosu/Graphics.hpp>
|
2
|
-
#include <Gosu/Bitmap.hpp>
|
3
|
-
#include <Gosu/IO.hpp>
|
4
|
-
#include <Gosu/Platform.hpp>
|
5
|
-
#include <Gosu/TR1.hpp>
|
6
|
-
#include <Gosu/Utility.hpp>
|
7
|
-
#include <Gosu/WinUtility.hpp>
|
8
|
-
#include <cwctype>
|
9
|
-
#include <map>
|
10
|
-
|
11
|
-
#include <objidl.h>
|
12
|
-
#include <gdiplus.h>
|
13
|
-
#include <windows.h>
|
14
|
-
|
15
|
-
using namespace std;
|
16
|
-
|
17
|
-
// TODO: Move into proper internal header
|
18
|
-
namespace Gosu { bool isExtension(const wchar_t* str, const wchar_t* ext); }
|
19
|
-
|
20
|
-
namespace
|
21
|
-
{
|
22
|
-
bool initialized = false;
|
23
|
-
ULONG_PTR token;
|
24
|
-
Gdiplus::GdiplusStartupInput input;
|
25
|
-
|
26
|
-
// TODO: Merge with BitmapFreeImage.cpp, somehow
|
27
|
-
void reshuffleBitmap(Gosu::Bitmap& bitmap)
|
28
|
-
{
|
29
|
-
// Since GDI+ only supports ARGB=BGRA formats, we
|
30
|
-
// manually exchange the R and B channels to get to ABGR=RGBA.
|
31
|
-
std::tr1::uint32_t* p = reinterpret_cast<std::tr1::uint32_t*>(bitmap.data());
|
32
|
-
for (int i = bitmap.width() * bitmap.height(); i > 0; --i, ++p)
|
33
|
-
*p = (*p & 0xff00ff00) | ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff);
|
34
|
-
}
|
35
|
-
|
36
|
-
void check(Gdiplus::Status status, const char* action)
|
37
|
-
{
|
38
|
-
if (status != Gdiplus::Ok)
|
39
|
-
throw runtime_error(string("A GDI+ error occured while ") + action);
|
40
|
-
}
|
41
|
-
|
42
|
-
void closeGDIplus()
|
43
|
-
{
|
44
|
-
Gdiplus::GdiplusShutdown(token);
|
45
|
-
}
|
46
|
-
|
47
|
-
void requireGDIplus()
|
48
|
-
{
|
49
|
-
if (initialized)
|
50
|
-
return;
|
51
|
-
initialized = true;
|
52
|
-
check(Gdiplus::GdiplusStartup(&token, &input, NULL), "initializing GDI+");
|
53
|
-
atexit(closeGDIplus);
|
54
|
-
}
|
55
|
-
|
56
|
-
void gdiPlusToGosu(Gosu::Bitmap& result, Gdiplus::Bitmap& bitmap)
|
57
|
-
{
|
58
|
-
result.resize(bitmap.GetWidth(), bitmap.GetHeight());
|
59
|
-
|
60
|
-
GUID guid;
|
61
|
-
check(bitmap.GetRawFormat(&guid), "getting the format GUID");
|
62
|
-
// TODO:
|
63
|
-
// if (guid == Gdiplus::ImageFormatJPEG || guid == Gdiplus::ImageFormatPNG ||
|
64
|
-
// guid == Gdiplus::ImageFormatGIF || guid == Gdiplus::ImageFormatBMP ||
|
65
|
-
// guid == Gdiplus::ImageFormatTIFF || guid == Gdiplus::ImageFormatIcon)
|
66
|
-
// else use FreeImage (via lazy linking...)
|
67
|
-
|
68
|
-
Gdiplus::BitmapData target;
|
69
|
-
target.Width = result.width();
|
70
|
-
target.Height = result.height();
|
71
|
-
target.PixelFormat = PixelFormat32bppARGB;
|
72
|
-
target.Stride = result.width() * 4;
|
73
|
-
target.Scan0 = result.data();
|
74
|
-
|
75
|
-
Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
|
76
|
-
|
77
|
-
check(bitmap.LockBits(&rect,
|
78
|
-
Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
|
79
|
-
PixelFormat32bppARGB, &target), "locking bits");
|
80
|
-
check(bitmap.UnlockBits(&target), "unlocking bits");
|
81
|
-
|
82
|
-
reshuffleBitmap(result);
|
83
|
-
|
84
|
-
if (guid == Gdiplus::ImageFormatBMP)
|
85
|
-
applyColorKey(result, Gosu::Color::FUCHSIA);
|
86
|
-
}
|
87
|
-
|
88
|
-
tr1::shared_ptr<IStream> readToIStream(Gosu::Reader reader)
|
89
|
-
{
|
90
|
-
unsigned remaining = reader.resource().size() - reader.position();
|
91
|
-
HGLOBAL buffer = ::GlobalAlloc(GMEM_MOVEABLE, remaining);
|
92
|
-
Gosu::Win::check(buffer);
|
93
|
-
void* bufferPtr = ::GlobalLock(buffer);
|
94
|
-
if (!bufferPtr)
|
95
|
-
{
|
96
|
-
::GlobalFree(buffer);
|
97
|
-
Gosu::Win::throwLastError();
|
98
|
-
}
|
99
|
-
reader.read(bufferPtr, reader.resource().size() - reader.position());
|
100
|
-
|
101
|
-
IStream* stream = NULL;
|
102
|
-
if (::CreateStreamOnHGlobal(buffer, TRUE, &stream) != S_OK)
|
103
|
-
{
|
104
|
-
::GlobalFree(buffer);
|
105
|
-
throw runtime_error("Could not create IStream");
|
106
|
-
}
|
107
|
-
return Gosu::Win::shareComPtr(stream);
|
108
|
-
}
|
109
|
-
|
110
|
-
CLSID& encoderFromMimeType(const wstring& mimeType)
|
111
|
-
{
|
112
|
-
static map<wstring, CLSID> cache;
|
113
|
-
if (cache.count(mimeType))
|
114
|
-
return cache[mimeType];
|
115
|
-
|
116
|
-
UINT num = 0, size = 0;
|
117
|
-
check(Gdiplus::GetImageEncodersSize(&num, &size), "counting encoders");
|
118
|
-
// Do the eleet int-based ceil(size / sizeof)
|
119
|
-
unsigned vecSize = (size + sizeof(Gdiplus::ImageCodecInfo) - 1) / sizeof(Gdiplus::ImageCodecInfo);
|
120
|
-
vector<Gdiplus::ImageCodecInfo> codecs(vecSize);
|
121
|
-
check(Gdiplus::GetImageEncoders(num, size,
|
122
|
-
&codecs[0]), "enumerating encoders");
|
123
|
-
for (int i = 0; i < num; ++i)
|
124
|
-
if (codecs[i].MimeType == mimeType)
|
125
|
-
return cache[mimeType] = codecs[i].Clsid;
|
126
|
-
throw runtime_error("No encoder found for " + Gosu::wstringToUTF8(mimeType));
|
127
|
-
}
|
128
|
-
|
129
|
-
CLSID encoderFromHint(const wstring& formatHint)
|
130
|
-
{
|
131
|
-
wstring::size_type idx = formatHint.rfind('.');
|
132
|
-
wstring mimeType = L"image/";
|
133
|
-
if (idx == wstring::npos)
|
134
|
-
mimeType += formatHint;
|
135
|
-
else
|
136
|
-
mimeType += formatHint.substr(idx + 1);
|
137
|
-
|
138
|
-
for (int i = 0; i < mimeType.size(); ++i)
|
139
|
-
mimeType[i] = towlower((wint_t)mimeType[i]);
|
140
|
-
|
141
|
-
// Fix pitfalls
|
142
|
-
if (mimeType == L"image/jpg")
|
143
|
-
mimeType = L"image/jpeg";
|
144
|
-
else if (mimeType == L"image/tif")
|
145
|
-
mimeType = L"image/tiff";
|
146
|
-
|
147
|
-
return encoderFromMimeType(mimeType);
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
void Gosu::loadImageFile(Gosu::Bitmap& result, const wstring& filename)
|
152
|
-
{
|
153
|
-
requireGDIplus();
|
154
|
-
|
155
|
-
Gdiplus::Bitmap bitmap(filename.c_str());
|
156
|
-
check(bitmap.GetLastStatus(), ("loading " + wstringToUTF8(filename)).c_str());
|
157
|
-
gdiPlusToGosu(result, bitmap);
|
158
|
-
}
|
159
|
-
|
160
|
-
void Gosu::loadImageFile(Gosu::Bitmap& result, Reader reader)
|
161
|
-
{
|
162
|
-
requireGDIplus();
|
163
|
-
|
164
|
-
tr1::shared_ptr<IStream> stream = readToIStream(reader);
|
165
|
-
Gdiplus::Bitmap bitmap(stream.get());
|
166
|
-
check(bitmap.GetLastStatus(), "loading a bitmap from memory");
|
167
|
-
gdiPlusToGosu(result, bitmap);
|
168
|
-
}
|
169
|
-
|
170
|
-
void Gosu::saveImageFile(const Bitmap& bitmap, const wstring& filename)
|
171
|
-
{
|
172
|
-
requireGDIplus();
|
173
|
-
|
174
|
-
Bitmap input = bitmap;
|
175
|
-
if (isExtension(filename.c_str(), L".bmp"))
|
176
|
-
unapplyColorKey(input, Color::FUCHSIA);
|
177
|
-
reshuffleBitmap(input);
|
178
|
-
Gdiplus::Bitmap output(input.width(), input.height(), input.width() * 4,
|
179
|
-
PixelFormat32bppARGB, (BYTE*)input.data());
|
180
|
-
check(output.GetLastStatus(), "creating a bitmap in memory");
|
181
|
-
|
182
|
-
check(output.Save(filename.c_str(), &encoderFromHint(filename)),
|
183
|
-
("writing to " + wstringToUTF8(filename)).c_str());
|
184
|
-
}
|
185
|
-
|
186
|
-
void Gosu::saveImageFile(const Bitmap& bitmap, Writer writer, const wstring& formatHint)
|
187
|
-
{
|
188
|
-
requireGDIplus();
|
189
|
-
|
190
|
-
Bitmap input = bitmap;
|
191
|
-
if (isExtension(formatHint.c_str(), L".bmp"))
|
192
|
-
unapplyColorKey(input, Color::FUCHSIA);
|
193
|
-
reshuffleBitmap(input);
|
194
|
-
Gdiplus::Bitmap output(input.width(), input.height(), input.width() * 4,
|
195
|
-
PixelFormat32bppARGB, (BYTE*)input.data());
|
196
|
-
check(output.GetLastStatus(), "creating a bitmap in memory");
|
197
|
-
|
198
|
-
IStream* stream = NULL;
|
199
|
-
if (CreateStreamOnHGlobal(0, TRUE, &stream) != S_OK)
|
200
|
-
throw runtime_error("Could not create IStream for writing");
|
201
|
-
tr1::shared_ptr<IStream> streamGuard(Gosu::Win::shareComPtr(stream));
|
202
|
-
check(output.Save(stream, &encoderFromHint(formatHint)),
|
203
|
-
"saving a bitmap to memory");
|
204
|
-
|
205
|
-
HGLOBAL buffer;
|
206
|
-
GetHGlobalFromStream(stream, &buffer);
|
207
|
-
void* bufferPtr = GlobalLock(buffer);
|
208
|
-
if (!bufferPtr)
|
209
|
-
Win::throwLastError();
|
210
|
-
writer.write(bufferPtr, GlobalSize(buffer));
|
211
|
-
GlobalUnlock(buffer);
|
212
|
-
}
|