gosu 0.9.2 → 0.10.0
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/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
|
-
}
|