You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

159 lines
3.4 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #if defined USE_GDIPLUS
  14. #include <algorithm>
  15. using namespace std;
  16. #include <windows.h>
  17. #include <gdiplus.h>
  18. #include "core.h"
  19. #include "../../image/image-private.h"
  20. namespace lol
  21. {
  22. /*
  23. * Image implementation class
  24. */
  25. DECLARE_IMAGE_LOADER(GdiPlusImageData, 100)
  26. {
  27. public:
  28. virtual bool Open(char const *);
  29. virtual bool Close();
  30. virtual void *GetData() const;
  31. private:
  32. Gdiplus::Bitmap *m_bitmap;
  33. Gdiplus::BitmapData m_bdata;
  34. };
  35. /*
  36. * Public Image class
  37. */
  38. bool GdiPlusImageData::Open(char const *path)
  39. {
  40. Gdiplus::Status status;
  41. ULONG_PTR token;
  42. Gdiplus::GdiplusStartupInput input;
  43. status = Gdiplus::GdiplusStartup(&token, &input, NULL);
  44. if (status != Gdiplus::Ok)
  45. {
  46. #if !LOL_RELEASE
  47. Log::Error("error %d while initialising GDI+\n", status);
  48. #endif
  49. return false;
  50. }
  51. Array<String> pathlist = System::GetPathList(path);
  52. m_bitmap = NULL;
  53. for (int i = 0; i < pathlist.Count(); ++i)
  54. {
  55. size_t len;
  56. len = mbstowcs(NULL, pathlist[i].C(), 0);
  57. wchar_t *wpath = new wchar_t[len + 1];
  58. if (mbstowcs(wpath, pathlist[i].C(), len + 1) == (size_t)-1)
  59. {
  60. #if !LOL_RELEASE
  61. Log::Error("invalid image name %s\n", pathlist[i].C());
  62. #endif
  63. delete[] wpath;
  64. continue;
  65. }
  66. status = Gdiplus::Ok;
  67. m_bitmap = Gdiplus::Bitmap::FromFile(wpath, 0);
  68. if (m_bitmap)
  69. {
  70. status = m_bitmap->GetLastStatus();
  71. if (status != Gdiplus::Ok)
  72. {
  73. #if !LOL_RELEASE
  74. if (status != Gdiplus::InvalidParameter)
  75. Log::Error("error %d loading %s\n",
  76. status, pathlist[i].C());
  77. #endif
  78. delete m_bitmap;
  79. m_bitmap = NULL;
  80. }
  81. }
  82. delete[] wpath;
  83. if (m_bitmap)
  84. break;
  85. }
  86. if (!m_bitmap)
  87. {
  88. #if !LOL_RELEASE
  89. Log::Error("could not load %s\n", path);
  90. #endif
  91. return false;
  92. }
  93. size = ivec2(m_bitmap->GetWidth(), m_bitmap->GetHeight());
  94. format = Image::FORMAT_RGBA;
  95. Gdiplus::Rect rect(0, 0, size.x, size.y);
  96. if(m_bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead,
  97. PixelFormat32bppARGB, &m_bdata) != Gdiplus::Ok)
  98. {
  99. #if !LOL_RELEASE
  100. Log::Error("could not lock bits in %s\n", path);
  101. #endif
  102. delete m_bitmap;
  103. return false;
  104. }
  105. /* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't
  106. * know about ARGB, only RGBA. So we swap bytes. We could also fix
  107. * this in the shader. */
  108. uint8_t *p = static_cast<uint8_t *>(m_bdata.Scan0);
  109. for (int y = 0; y < size.y; y++)
  110. for (int x = 0; x < size.x; x++)
  111. {
  112. uint8_t tmp = p[2];
  113. p[2] = p[0];
  114. p[0] = tmp;
  115. p += 4;
  116. }
  117. return true;
  118. }
  119. bool GdiPlusImageData::Close()
  120. {
  121. m_bitmap->UnlockBits(&m_bdata);
  122. delete m_bitmap;
  123. return true;
  124. }
  125. void * GdiPlusImageData::GetData() const
  126. {
  127. return m_bdata.Scan0;
  128. }
  129. } /* namespace lol */
  130. #endif /* defined USE_GDIPLUS */