test_bit_map.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /**************************************************************************/
  2. /* test_bit_map.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #ifndef TEST_BIT_MAP_H
  31. #define TEST_BIT_MAP_H
  32. #include "core/os/memory.h"
  33. #include "scene/resources/bit_map.h"
  34. #include "tests/test_macros.h"
  35. namespace TestBitmap {
  36. void reset_bit_map(BitMap &p_bm) {
  37. Size2i size = p_bm.get_size();
  38. p_bm.set_bit_rect(Rect2i(0, 0, size.width, size.height), false);
  39. }
  40. TEST_CASE("[BitMap] Create bit map") {
  41. Size2i dim{ 256, 512 };
  42. BitMap bit_map{};
  43. bit_map.create(dim);
  44. CHECK(bit_map.get_size() == Size2i(256, 512));
  45. CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "This will go through the entire bitmask inside of bitmap, thus hopefully checking if the bitmask was correctly set up.");
  46. ERR_PRINT_OFF
  47. dim = Size2i(0, 256);
  48. bit_map.create(dim);
  49. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is invalid.");
  50. dim = Size2i(512, 0);
  51. bit_map.create(dim);
  52. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is invalid.");
  53. dim = Size2i(46341, 46341);
  54. bit_map.create(dim);
  55. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is too large (46341*46341=2147488281).");
  56. ERR_PRINT_ON
  57. }
  58. TEST_CASE("[BitMap] Create bit map from image alpha") {
  59. const Size2i dim{ 256, 256 };
  60. BitMap bit_map{};
  61. bit_map.create(dim);
  62. ERR_PRINT_OFF
  63. const Ref<Image> null_img = nullptr;
  64. bit_map.create_from_image_alpha(null_img);
  65. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because bitmap creation from a nullptr should fail.");
  66. Ref<Image> empty_img;
  67. empty_img.instantiate();
  68. bit_map.create_from_image_alpha(empty_img);
  69. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because bitmap creation from an empty image should fail.");
  70. Ref<Image> wrong_format_img = Image::create_empty(3, 3, false, Image::Format::FORMAT_DXT1);
  71. bit_map.create_from_image_alpha(wrong_format_img);
  72. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because converting from a compressed image should fail.");
  73. ERR_PRINT_ON
  74. Ref<Image> img = Image::create_empty(3, 3, false, Image::Format::FORMAT_RGBA8);
  75. img->set_pixel(0, 0, Color(0, 0, 0, 0));
  76. img->set_pixel(0, 1, Color(0, 0, 0, 0.09f));
  77. img->set_pixel(0, 2, Color(0, 0, 0, 0.25f));
  78. img->set_pixel(1, 0, Color(0, 0, 0, 0.5f));
  79. img->set_pixel(1, 1, Color(0, 0, 0, 0.75f));
  80. img->set_pixel(1, 2, Color(0, 0, 0, 0.99f));
  81. img->set_pixel(2, 0, Color(0, 0, 0, 1.f));
  82. // Check different threshold values.
  83. bit_map.create_from_image_alpha(img);
  84. CHECK_MESSAGE(bit_map.get_true_bit_count() == 5, "There are 5 values in the image that are smaller than the default threshold of 0.1.");
  85. bit_map.create_from_image_alpha(img, 0.08f);
  86. CHECK_MESSAGE(bit_map.get_true_bit_count() == 6, "There are 6 values in the image that are smaller than the threshold of 0.08.");
  87. bit_map.create_from_image_alpha(img, 1);
  88. CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "There are no values in the image that are smaller than the threshold of 1, there is one value equal to 1, but we check for inequality only.");
  89. }
  90. TEST_CASE("[BitMap] Set bit") {
  91. Size2i dim{ 256, 256 };
  92. BitMap bit_map{};
  93. // Setting a point before a bit map is created should not crash, because there are checks to see if we are out of bounds.
  94. ERR_PRINT_OFF
  95. bit_map.set_bitv(Point2i(128, 128), true);
  96. bit_map.create(dim);
  97. CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "All values should be initialized to false.");
  98. bit_map.set_bitv(Point2i(128, 128), true);
  99. CHECK_MESSAGE(bit_map.get_true_bit_count() == 1, "One bit should be set to true.");
  100. CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 128)) == true, "The bit at (128,128) should be set to true");
  101. bit_map.set_bitv(Point2i(128, 128), false);
  102. CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "The bit should now be set to false again");
  103. CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 128)) == false, "The bit at (128,128) should now be set to false again");
  104. bit_map.create(dim);
  105. bit_map.set_bitv(Point2i(512, 512), true);
  106. CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "Nothing should change as we were trying to edit a bit outside of the correct range.");
  107. ERR_PRINT_ON
  108. }
  109. TEST_CASE("[BitMap] Get bit") {
  110. const Size2i dim{ 256, 256 };
  111. BitMap bit_map{};
  112. ERR_PRINT_OFF
  113. CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 128)) == false, "Trying to access a bit outside of the BitMap's range should always return false");
  114. bit_map.create(dim);
  115. CHECK(bit_map.get_bitv(Point2i(128, 128)) == false);
  116. bit_map.set_bit_rect(Rect2i(-1, -1, 257, 257), true);
  117. // Checking that range is [0, 256).
  118. CHECK(bit_map.get_bitv(Point2i(-1, 0)) == false);
  119. CHECK(bit_map.get_bitv(Point2i(0, 0)) == true);
  120. CHECK(bit_map.get_bitv(Point2i(128, 128)) == true);
  121. CHECK(bit_map.get_bitv(Point2i(255, 255)) == true);
  122. CHECK(bit_map.get_bitv(Point2i(256, 256)) == false);
  123. CHECK(bit_map.get_bitv(Point2i(257, 257)) == false);
  124. ERR_PRINT_ON
  125. }
  126. TEST_CASE("[BitMap] Set bit rect") {
  127. const Size2i dim{ 256, 256 };
  128. BitMap bit_map{};
  129. // Although we have not setup the BitMap yet, this should not crash because we get an empty intersection inside of the method.
  130. bit_map.set_bit_rect(Rect2i{ 0, 0, 128, 128 }, true);
  131. bit_map.create(dim);
  132. CHECK(bit_map.get_true_bit_count() == 0);
  133. bit_map.set_bit_rect(Rect2i{ 0, 0, 256, 256 }, true);
  134. CHECK(bit_map.get_true_bit_count() == 65536);
  135. reset_bit_map(bit_map);
  136. // Checking out of bounds handling.
  137. ERR_PRINT_OFF
  138. bit_map.set_bit_rect(Rect2i{ 128, 128, 256, 256 }, true);
  139. CHECK(bit_map.get_true_bit_count() == 16384);
  140. reset_bit_map(bit_map);
  141. bit_map.set_bit_rect(Rect2i{ -128, -128, 256, 256 }, true);
  142. CHECK(bit_map.get_true_bit_count() == 16384);
  143. reset_bit_map(bit_map);
  144. bit_map.set_bit_rect(Rect2i{ -128, -128, 512, 512 }, true);
  145. CHECK(bit_map.get_true_bit_count() == 65536);
  146. ERR_PRINT_ON
  147. }
  148. TEST_CASE("[BitMap] Get true bit count") {
  149. const Size2i dim{ 256, 256 };
  150. BitMap bit_map{};
  151. CHECK(bit_map.get_true_bit_count() == 0);
  152. bit_map.create(dim);
  153. CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "Uninitialized bit map should have no true bits");
  154. bit_map.set_bit_rect(Rect2i{ 0, 0, 256, 256 }, true);
  155. CHECK(bit_map.get_true_bit_count() == 65536);
  156. bit_map.set_bitv(Point2i{ 0, 0 }, false);
  157. CHECK(bit_map.get_true_bit_count() == 65535);
  158. bit_map.set_bit_rect(Rect2i{ 0, 0, 256, 256 }, false);
  159. CHECK(bit_map.get_true_bit_count() == 0);
  160. }
  161. TEST_CASE("[BitMap] Get size") {
  162. const Size2i dim{ 256, 256 };
  163. BitMap bit_map{};
  164. CHECK_MESSAGE(bit_map.get_size() == Size2i(0, 0), "Uninitialized bit map should have a size of 0x0");
  165. bit_map.create(dim);
  166. CHECK(bit_map.get_size() == Size2i(256, 256));
  167. ERR_PRINT_OFF
  168. bit_map.create(Size2i(-1, 0));
  169. ERR_PRINT_ON
  170. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Invalid size should not be accepted by create");
  171. bit_map.create(Size2i(256, 128));
  172. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 128), "Bitmap should have updated size");
  173. }
  174. TEST_CASE("[BitMap] Resize") {
  175. const Size2i dim{ 128, 128 };
  176. BitMap bit_map{};
  177. bit_map.resize(dim);
  178. CHECK(bit_map.get_size() == dim);
  179. bit_map.create(dim);
  180. bit_map.set_bit_rect(Rect2i(0, 0, 10, 10), true);
  181. bit_map.set_bit_rect(Rect2i(118, 118, 10, 10), true);
  182. CHECK_MESSAGE(bit_map.get_true_bit_count() == 200, "There should be 100 bits in the top left corner, and 100 bits in the bottom right corner");
  183. bit_map.resize(Size2i(64, 64));
  184. CHECK_MESSAGE(bit_map.get_true_bit_count() == 50, "There should be 25 bits in the top left corner, and 25 bits in the bottom right corner");
  185. bit_map.create(dim);
  186. ERR_PRINT_OFF
  187. bit_map.resize(Size2i(-1, 128));
  188. ERR_PRINT_ON
  189. CHECK_MESSAGE(bit_map.get_size() == Size2i(128, 128), "When an invalid size is given the bit map will keep its size");
  190. bit_map.create(dim);
  191. bit_map.set_bit_rect(Rect2i(0, 0, 10, 10), true);
  192. bit_map.set_bit_rect(Rect2i(118, 118, 10, 10), true);
  193. CHECK_MESSAGE(bit_map.get_true_bit_count() == 200, "There should be 100 bits in the top left corner, and 100 bits in the bottom right corner");
  194. bit_map.resize(Size2i(256, 256));
  195. CHECK_MESSAGE(bit_map.get_true_bit_count() == 800, "There should still be 100 bits in the bottom right corner, and all new bits should be initialized to false");
  196. CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "The bitmap should now be 256x256");
  197. }
  198. TEST_CASE("[BitMap] Grow and shrink mask") {
  199. const Size2i dim{ 256, 256 };
  200. BitMap bit_map{};
  201. ERR_PRINT_OFF
  202. bit_map.grow_mask(100, Rect2i(0, 0, 128, 128)); // Check if method does not crash when working with an uninitialized bit map.
  203. ERR_PRINT_ON
  204. CHECK_MESSAGE(bit_map.get_size() == Size2i(0, 0), "Size should still be equal to 0x0");
  205. bit_map.create(dim);
  206. bit_map.set_bit_rect(Rect2i(96, 96, 64, 64), true);
  207. CHECK_MESSAGE(bit_map.get_true_bit_count() == 4096, "Creating a square of 64x64 should be 4096 bits");
  208. bit_map.grow_mask(0, Rect2i(0, 0, 256, 256));
  209. CHECK_MESSAGE(bit_map.get_true_bit_count() == 4096, "Growing with size of 0 should not change any bits");
  210. reset_bit_map(bit_map);
  211. bit_map.set_bit_rect(Rect2i(96, 96, 64, 64), true);
  212. CHECK_MESSAGE(bit_map.get_bitv(Point2i(95, 128)) == false, "Bits just outside of the square should not be set");
  213. CHECK_MESSAGE(bit_map.get_bitv(Point2i(160, 128)) == false, "Bits just outside of the square should not be set");
  214. CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 95)) == false, "Bits just outside of the square should not be set");
  215. CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 160)) == false, "Bits just outside of the square should not be set");
  216. bit_map.grow_mask(1, Rect2i(0, 0, 256, 256));
  217. CHECK_MESSAGE(bit_map.get_true_bit_count() == 4352, "We should have 4*64 (perimeter of square) more bits set to true");
  218. CHECK_MESSAGE(bit_map.get_bitv(Point2i(95, 128)) == true, "Bits that were just outside of the square should now be set to true");
  219. CHECK_MESSAGE(bit_map.get_bitv(Point2i(160, 128)) == true, "Bits that were just outside of the square should now be set to true");
  220. CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 95)) == true, "Bits that were just outside of the square should now be set to true");
  221. CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 160)) == true, "Bits that were just outside of the square should now be set to true");
  222. reset_bit_map(bit_map);
  223. bit_map.set_bit_rect(Rect2i(127, 127, 1, 1), true);
  224. CHECK(bit_map.get_true_bit_count() == 1);
  225. bit_map.grow_mask(32, Rect2i(0, 0, 256, 256));
  226. CHECK_MESSAGE(bit_map.get_true_bit_count() == 3209, "Creates a circle around the initial bit with a radius of 32 bits. Any bit that has a distance within this radius will be set to true");
  227. reset_bit_map(bit_map);
  228. bit_map.set_bit_rect(Rect2i(127, 127, 1, 1), true);
  229. for (int i = 0; i < 32; i++) {
  230. bit_map.grow_mask(1, Rect2i(0, 0, 256, 256));
  231. }
  232. CHECK_MESSAGE(bit_map.get_true_bit_count() == 2113, "Creates a diamond around the initial bit with diagonals that are 65 bits long.");
  233. reset_bit_map(bit_map);
  234. bit_map.set_bit_rect(Rect2i(123, 123, 10, 10), true);
  235. CHECK(bit_map.get_true_bit_count() == 100);
  236. bit_map.grow_mask(-11, Rect2i(0, 0, 256, 256));
  237. CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "Shrinking by more than the width of the square should totally remove it.");
  238. reset_bit_map(bit_map);
  239. bit_map.set_bit_rect(Rect2i(96, 96, 64, 64), true);
  240. CHECK_MESSAGE(bit_map.get_bitv(Point2i(96, 129)) == true, "Bits on the edge of the square should be true");
  241. CHECK_MESSAGE(bit_map.get_bitv(Point2i(159, 129)) == true, "Bits on the edge of the square should be true");
  242. CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 96)) == true, "Bits on the edge of the square should be true");
  243. CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 159)) == true, "Bits on the edge of the square should be true");
  244. bit_map.grow_mask(-1, Rect2i(0, 0, 256, 256));
  245. CHECK_MESSAGE(bit_map.get_true_bit_count() == 3844, "Shrinking by 1 should set 4*63=252 bits to false");
  246. CHECK_MESSAGE(bit_map.get_bitv(Point2i(96, 129)) == false, "Bits that were on the edge of the square should now be set to false");
  247. CHECK_MESSAGE(bit_map.get_bitv(Point2i(159, 129)) == false, "Bits that were on the edge of the square should now be set to false");
  248. CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 96)) == false, "Bits that were on the edge of the square should now be set to false");
  249. CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 159)) == false, "Bits that were on the edge of the square should now be set to false");
  250. reset_bit_map(bit_map);
  251. bit_map.set_bit_rect(Rect2i(125, 125, 1, 6), true);
  252. bit_map.set_bit_rect(Rect2i(130, 125, 1, 6), true);
  253. bit_map.set_bit_rect(Rect2i(125, 130, 6, 1), true);
  254. CHECK(bit_map.get_true_bit_count() == 16);
  255. CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 131)) == false, "Bits that are on the edge of the shape should be set to false");
  256. CHECK_MESSAGE(bit_map.get_bitv(Point2i(131, 131)) == false, "Bits that are on the edge of the shape should be set to false");
  257. CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 124)) == false, "Bits that are on the edge of the shape should be set to false");
  258. CHECK_MESSAGE(bit_map.get_bitv(Point2i(130, 124)) == false, "Bits that are on the edge of the shape should be set to false");
  259. bit_map.grow_mask(1, Rect2i(0, 0, 256, 256));
  260. CHECK(bit_map.get_true_bit_count() == 48);
  261. CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 131)) == true, "Bits that were on the edge of the shape should now be set to true");
  262. CHECK_MESSAGE(bit_map.get_bitv(Point2i(131, 130)) == true, "Bits that were on the edge of the shape should now be set to true");
  263. CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 124)) == true, "Bits that were on the edge of the shape should now be set to true");
  264. CHECK_MESSAGE(bit_map.get_bitv(Point2i(130, 124)) == true, "Bits that were on the edge of the shape should now be set to true");
  265. CHECK_MESSAGE(bit_map.get_bitv(Point2i(124, 124)) == false, "Bits that are on the edge of the shape should be set to false");
  266. CHECK_MESSAGE(bit_map.get_bitv(Point2i(126, 124)) == false, "Bits that are on the edge of the shape should be set to false");
  267. CHECK_MESSAGE(bit_map.get_bitv(Point2i(124, 131)) == false, "Bits that are on the edge of the shape should be set to false");
  268. CHECK_MESSAGE(bit_map.get_bitv(Point2i(131, 131)) == false, "Bits that are on the edge of the shape should be set to false");
  269. }
  270. TEST_CASE("[BitMap] Blit") {
  271. Point2i blit_pos{ 128, 128 };
  272. Point2i bit_map_size{ 256, 256 };
  273. Point2i blit_size{ 32, 32 };
  274. BitMap bit_map{};
  275. Ref<BitMap> blit_bit_map{};
  276. // Testing null reference to blit bit map.
  277. ERR_PRINT_OFF
  278. bit_map.blit(blit_pos, blit_bit_map);
  279. ERR_PRINT_ON
  280. blit_bit_map.instantiate();
  281. // Testing if uninitialized blit bit map and uninitialized bit map does not crash
  282. bit_map.blit(blit_pos, blit_bit_map);
  283. // Testing if uninitialized bit map does not crash
  284. blit_bit_map->create(blit_size);
  285. bit_map.blit(blit_pos, blit_bit_map);
  286. // Testing if uninitialized bit map does not crash
  287. blit_bit_map.unref();
  288. blit_bit_map.instantiate();
  289. CHECK_MESSAGE(blit_bit_map->get_size() == Point2i(0, 0), "Size should be cleared by unref and instance calls.");
  290. bit_map.create(bit_map_size);
  291. bit_map.blit(Point2i(128, 128), blit_bit_map);
  292. // Testing if both initialized does not crash.
  293. blit_bit_map->create(blit_size);
  294. bit_map.blit(blit_pos, blit_bit_map);
  295. bit_map.set_bit_rect(Rect2i{ 127, 127, 3, 3 }, true);
  296. CHECK(bit_map.get_true_bit_count() == 9);
  297. bit_map.blit(Point2i(112, 112), blit_bit_map);
  298. CHECK_MESSAGE(bit_map.get_true_bit_count() == 9, "No bits should have been changed, as the blit bit map only contains falses");
  299. bit_map.create(bit_map_size);
  300. blit_bit_map->create(blit_size);
  301. blit_bit_map->set_bit_rect(Rect2i(15, 15, 3, 3), true);
  302. CHECK(blit_bit_map->get_true_bit_count() == 9);
  303. CHECK(bit_map.get_true_bit_count() == 0);
  304. bit_map.blit(Point2i(112, 112), blit_bit_map);
  305. CHECK_MESSAGE(bit_map.get_true_bit_count() == 9, "All true bits should have been moved to the bit map");
  306. for (int x = 127; x < 129; ++x) {
  307. for (int y = 127; y < 129; ++y) {
  308. CHECK_MESSAGE(bit_map.get_bitv(Point2i(x, y)) == true, "All true bits should have been moved to the bit map");
  309. }
  310. }
  311. }
  312. TEST_CASE("[BitMap] Convert to image") {
  313. const Size2i dim{ 256, 256 };
  314. BitMap bit_map{};
  315. Ref<Image> img;
  316. ERR_PRINT_OFF
  317. img = bit_map.convert_to_image();
  318. ERR_PRINT_ON
  319. CHECK_MESSAGE(img.is_valid(), "We should receive a valid Image Object even if BitMap is not created yet");
  320. CHECK_MESSAGE(img->get_format() == Image::FORMAT_L8, "We should receive a valid Image Object even if BitMap is not created yet");
  321. CHECK_MESSAGE(img->get_size() == (Size2i(0, 0)), "Image should have no width or height, because BitMap has not yet been created");
  322. bit_map.create(dim);
  323. img = bit_map.convert_to_image();
  324. CHECK_MESSAGE(img->get_size() == dim, "Image should have the same dimensions as the BitMap");
  325. CHECK_MESSAGE(img->get_pixel(0, 0).is_equal_approx(Color(0, 0, 0)), "BitMap is initialized to all 0's, so Image should be all black");
  326. reset_bit_map(bit_map);
  327. bit_map.set_bit_rect(Rect2i(0, 0, 128, 128), true);
  328. img = bit_map.convert_to_image();
  329. CHECK_MESSAGE(img->get_pixel(0, 0).is_equal_approx(Color(1, 1, 1)), "BitMap's top-left quadrant is all 1's, so Image should be white");
  330. CHECK_MESSAGE(img->get_pixel(255, 255).is_equal_approx(Color(0, 0, 0)), "All other quadrants were 0's, so these should be black");
  331. }
  332. TEST_CASE("[BitMap] Clip to polygon") {
  333. const Size2i dim{ 256, 256 };
  334. BitMap bit_map{};
  335. Vector<Vector<Vector2>> polygons;
  336. ERR_PRINT_OFF
  337. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
  338. ERR_PRINT_ON
  339. CHECK_MESSAGE(polygons.size() == 0, "We should have no polygons, because the BitMap was not initialized");
  340. bit_map.create(dim);
  341. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
  342. CHECK_MESSAGE(polygons.size() == 0, "We should have no polygons, because the BitMap was all 0's");
  343. reset_bit_map(bit_map);
  344. bit_map.set_bit_rect(Rect2i(0, 0, 64, 64), true);
  345. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
  346. CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
  347. CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
  348. reset_bit_map(bit_map);
  349. bit_map.set_bit_rect(Rect2i(0, 0, 32, 32), true);
  350. bit_map.set_bit_rect(Rect2i(64, 64, 32, 32), true);
  351. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
  352. CHECK_MESSAGE(polygons.size() == 2, "We should have exactly 2 polygons");
  353. CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
  354. CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
  355. reset_bit_map(bit_map);
  356. bit_map.set_bit_rect(Rect2i(124, 112, 8, 32), true);
  357. bit_map.set_bit_rect(Rect2i(112, 124, 32, 8), true);
  358. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 256, 256));
  359. CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
  360. CHECK_MESSAGE(polygons[0].size() == 12, "The polygon should have exactly 12 points");
  361. reset_bit_map(bit_map);
  362. bit_map.set_bit_rect(Rect2i(124, 112, 8, 32), true);
  363. bit_map.set_bit_rect(Rect2i(112, 124, 32, 8), true);
  364. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
  365. CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
  366. CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points");
  367. reset_bit_map(bit_map);
  368. bit_map.set_bit_rect(Rect2i(0, 0, 64, 64), true);
  369. bit_map.set_bit_rect(Rect2i(64, 64, 64, 64), true);
  370. bit_map.set_bit_rect(Rect2i(192, 128, 64, 64), true);
  371. bit_map.set_bit_rect(Rect2i(128, 192, 64, 64), true);
  372. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 256, 256));
  373. CHECK_MESSAGE(polygons.size() == 4, "We should have exactly 4 polygons");
  374. CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
  375. CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
  376. CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points");
  377. CHECK_MESSAGE(polygons[3].size() == 4, "The polygon should have exactly 4 points");
  378. reset_bit_map(bit_map);
  379. bit_map.set_bit(0, 0, true);
  380. bit_map.set_bit(2, 0, true);
  381. bit_map.set_bit_rect(Rect2i(1, 1, 1, 2), true);
  382. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 3, 3));
  383. CHECK_MESSAGE(polygons.size() == 3, "We should have exactly 3 polygons");
  384. CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
  385. CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
  386. CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points");
  387. reset_bit_map(bit_map);
  388. bit_map.set_bit_rect(Rect2i(0, 0, 2, 1), true);
  389. bit_map.set_bit_rect(Rect2i(0, 2, 3, 1), true);
  390. bit_map.set_bit(0, 1, true);
  391. bit_map.set_bit(2, 1, true);
  392. polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 4, 4));
  393. CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
  394. CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points");
  395. }
  396. } // namespace TestBitmap
  397. #endif // TEST_BIT_MAP_H