|
- //
- // Lol Engine
- //
- // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the Do What The Fuck You Want To
- // Public License, Version 2, as published by Sam Hocevar. See
- // http://www.wtfpl.net/ for more details.
- //
-
- #if defined HAVE_CONFIG_H
- # include "config.h"
- #endif
-
- #if defined USE_GDIPLUS
-
- #include <algorithm>
-
- using namespace std;
-
- #include <windows.h>
- #include <gdiplus.h>
-
- #include "core.h"
- #include "../../image/image-private.h"
-
- namespace lol
- {
-
- /*
- * Image implementation class
- */
-
- DECLARE_IMAGE_LOADER(GdiPlusImageData, 100)
- {
- public:
- virtual bool Open(char const *);
- virtual bool Close();
-
- virtual void *GetData() const;
-
- private:
- Gdiplus::Bitmap *m_bitmap;
- Gdiplus::BitmapData m_bdata;
- };
-
- /*
- * Public Image class
- */
-
- bool GdiPlusImageData::Open(char const *path)
- {
- Gdiplus::Status status;
- ULONG_PTR token;
- Gdiplus::GdiplusStartupInput input;
- status = Gdiplus::GdiplusStartup(&token, &input, NULL);
- if (status != Gdiplus::Ok)
- {
- #if !LOL_RELEASE
- Log::Error("error %d while initialising GDI+\n", status);
- #endif
- return false;
- }
-
- Array<String> pathlist = System::GetPathList(path);
- m_bitmap = NULL;
- for (int i = 0; i < pathlist.Count(); ++i)
- {
- size_t len;
- len = mbstowcs(NULL, pathlist[i].C(), 0);
- wchar_t *wpath = new wchar_t[len + 1];
- if (mbstowcs(wpath, pathlist[i].C(), len + 1) == (size_t)-1)
- {
- #if !LOL_RELEASE
- Log::Error("invalid image name %s\n", pathlist[i].C());
- #endif
- delete[] wpath;
- continue;
- }
-
- status = Gdiplus::Ok;
- m_bitmap = Gdiplus::Bitmap::FromFile(wpath, 0);
-
- if (m_bitmap)
- {
- status = m_bitmap->GetLastStatus();
- if (status != Gdiplus::Ok)
- {
- #if !LOL_RELEASE
- if (status != Gdiplus::InvalidParameter)
- Log::Error("error %d loading %s\n",
- status, pathlist[i].C());
- #endif
- delete m_bitmap;
- m_bitmap = NULL;
- }
- }
-
- delete[] wpath;
- if (m_bitmap)
- break;
- }
-
- if (!m_bitmap)
- {
- #if !LOL_RELEASE
- Log::Error("could not load %s\n", path);
- #endif
- return false;
- }
-
- size = ivec2(m_bitmap->GetWidth(), m_bitmap->GetHeight());
- format = Image::FORMAT_RGBA;
-
- Gdiplus::Rect rect(0, 0, size.x, size.y);
- if(m_bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead,
- PixelFormat32bppARGB, &m_bdata) != Gdiplus::Ok)
- {
- #if !LOL_RELEASE
- Log::Error("could not lock bits in %s\n", path);
- #endif
- delete m_bitmap;
- return false;
- }
-
- /* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't
- * know about ARGB, only RGBA. So we swap bytes. We could also fix
- * this in the shader. */
- uint8_t *p = static_cast<uint8_t *>(m_bdata.Scan0);
- for (int y = 0; y < size.y; y++)
- for (int x = 0; x < size.x; x++)
- {
- uint8_t tmp = p[2];
- p[2] = p[0];
- p[0] = tmp;
- p += 4;
- }
-
- return true;
- }
-
- bool GdiPlusImageData::Close()
- {
- m_bitmap->UnlockBits(&m_bdata);
- delete m_bitmap;
-
- return true;
- }
-
- void * GdiPlusImageData::GetData() const
- {
- return m_bdata.Scan0;
- }
-
- } /* namespace lol */
-
- #endif /* defined USE_GDIPLUS */
|