The Battle for Wesnoth  1.19.0-dev
test_image_modifications.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2024
3  by Karol Kozub <karol.alt@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-test"
17 
18 #include <boost/test/unit_test.hpp>
19 #include <sstream>
20 
21 #include "game_config.hpp"
22 #include "game_config_view.hpp"
23 #include "config_cache.hpp"
24 #include "config.hpp"
25 #include "color_range.hpp"
26 #include "picture.hpp"
27 #include "image_modifications.hpp"
28 #include "log.hpp"
29 #include "filesystem.hpp"
30 
31 using namespace image;
32 
33 namespace {
34 /** Sets up the environment for every test */
35 class environment_setup
36 {
37 public:
38  environment_setup()
39  // redirects the output to an ignored stream
40  : ignored_stream_()
41  , output_redirect_(ignored_stream_)
42  , paths_manager_()
43  {
44  set_up_color_info();
45  set_up_image_paths();
46  }
47 
48 private:
49  /** Sets up color_info configuration
50  *
51  * This is required by the RC modifications
52  */
53  void set_up_color_info()
54  {
55  config cfg;
56  cfg.add_child("color_range",
57  create_color_range("red",
58  "FF0000,FFFFFF,000000,FF0000",
59  "Red"));
60  cfg.add_child("color_range",
61  create_color_range("blue",
62  "2E419B,FFFFFF,0F0F0F,0000FF",
63  "Blue"));
64 
66  }
67 
68  /** Sets up the paths later used to load images
69  *
70  * This is required by all the modifications that use image::get_surface
71  * to load images from disk
72  */
73  void set_up_image_paths()
74  {
75  config cfg;
77  cfg.add_child("binary_path",
78  create_path_config("data/core"));
79 
80 
81  paths_manager_.set_paths(v);
82  }
83 
84  static config create_color_range(const std::string& id,
85  const std::string& rgb,
86  const std::string& name)
87  {
88  config cfg;
89 
90  cfg["id"] = id;
91  cfg["rgb"] = rgb;
92  cfg["name"] = name;
93 
94  return cfg;
95  }
96 
97  static config create_path_config(const std::string& path)
98  {
99  config cfg;
100 
101  cfg["path"] = path;
102 
103  return cfg;
104  }
105 
106  std::stringstream ignored_stream_;
107  lg::redirect_output_setter output_redirect_;
108  filesystem::binary_paths_manager paths_manager_;
109 };
110 } // anonymous namespace
111 
112 BOOST_AUTO_TEST_SUITE(image_modification_parsing)
113 
114 /** Tests if modifications with a higher priority are placed before the others
115  *
116  * The RC modification has a higher priority than other modifications and has
117  * to be applied before all the others. This test checks if that order is taken
118  * care of by the queue.
119  */
120 BOOST_AUTO_TEST_CASE(test_modificaiton_queue_order)
121 {
122  environment_setup env_setup;
123 
124  modification_queue queue;
125 
126  auto low_priority_mod = std::make_unique<fl_modification>();
127  auto high_priority_mod = std::make_unique<rc_modification>();
128 
129  modification* lptr = low_priority_mod.get();
130  modification* hptr = high_priority_mod.get();
131 
132  queue.push(std::move(low_priority_mod));
133  queue.push(std::move(high_priority_mod));
134 
135  BOOST_REQUIRE_EQUAL(queue.size(), 2);
136 
137  BOOST_CHECK_EQUAL(queue.top(), hptr);
138  queue.pop();
139  BOOST_CHECK_EQUAL(queue.top(), lptr);
140  queue.pop();
141 
142  low_priority_mod = std::make_unique<fl_modification>();
143  high_priority_mod = std::make_unique<rc_modification>();
144 
145  lptr = low_priority_mod.get();
146  hptr = high_priority_mod.get();
147 
148  // reverse insertion order now
149  queue.push(std::move(high_priority_mod));
150  queue.push(std::move(low_priority_mod));
151 
152  BOOST_REQUIRE_EQUAL(queue.size(), 2);
153 
154  BOOST_CHECK_EQUAL(queue.top(), hptr);
155  queue.pop();
156  BOOST_CHECK_EQUAL(queue.top(), lptr);
157  queue.pop();
158 }
159 
160 /** Tests if the TC modification is correctly decoded */
161 BOOST_AUTO_TEST_CASE(test_tc_modification_decoding)
162 {
163  environment_setup env_setup;
164 
165  modification_queue queue = modification::decode("~TC(1,blue)");
166 
167  BOOST_REQUIRE_EQUAL(queue.size(), 1);
168 
169  rc_modification* mod = dynamic_cast<rc_modification*>(queue.top());
170 
171  // The dynamic_cast returns nullptr if the argument doesn't match the type
172  BOOST_REQUIRE(mod != nullptr);
173 
174  const std::vector<color_t>& old_color = game_config::tc_info("blue");
175  // The first team color is red
176  const color_range& new_color = game_config::color_info("red");
177  color_range_map expected = recolor_range(new_color, old_color);
178 
179  BOOST_CHECK(expected == mod->map());
180 }
181 
182 /** Tests if the TC modification with invalid arguments is ignored */
183 BOOST_AUTO_TEST_CASE(test_tc_modification_decoding_invalid_args)
184 {
185  environment_setup env_setup;
186 
187  modification_queue queue = modification::decode("~TC()~TC(1)~TC(0,blue)");
188 
189  BOOST_REQUIRE_EQUAL(queue.size(), 0);
190 }
191 
192 /** Tests if the RC modification is correctly decoded */
193 BOOST_AUTO_TEST_CASE(test_rc_modification_decoding)
194 {
195  environment_setup env_setup;
196 
197  modification_queue queue = modification::decode("~RC(red>blue)");
198 
199  BOOST_REQUIRE_EQUAL(queue.size(), 1);
200 
201  rc_modification* mod = dynamic_cast<rc_modification*>(queue.top());
202 
203  // The dynamic_cast returns nullptr if the argument doesn't match the type
204  BOOST_REQUIRE(mod != nullptr);
205 
206  const std::vector<color_t>& old_color = game_config::tc_info("red");
207  const color_range& new_color = game_config::color_info("blue");
208  color_range_map expected = recolor_range(new_color, old_color);
209 
210  BOOST_CHECK(expected == mod->map());
211 }
212 
213 /** Tests if the RC modification with invalid arguments is ignored */
214 BOOST_AUTO_TEST_CASE(test_rc_modification_decoding_invalid_args)
215 {
216  environment_setup env_setup;
217 
218  modification_queue queue = modification::decode("~RC()~RC(blue)~RC(>)");
219 
220  BOOST_REQUIRE_EQUAL(queue.size(), 0);
221 }
222 
223 /** Tests if the PAL modification is correctly decoded */
224 BOOST_AUTO_TEST_CASE(test_pal_modification_decoding)
225 {
226  environment_setup env_setup;
227 
228  modification_queue queue =
229  modification::decode("~PAL(000000,005000 > FFFFFF,FF00FF)");
230 
231  BOOST_REQUIRE_EQUAL(queue.size(), 1);
232 
233  rc_modification* mod = dynamic_cast<rc_modification*>(queue.top());
234 
235  // The dynamic_cast returns nullptr if the argument doesn't match the type
236  BOOST_REQUIRE(mod != nullptr);
237 
238  const std::vector<color_t>& old_palette = game_config::tc_info("000000,005000");
239  const std::vector<color_t>& new_palette = game_config::tc_info("FFFFFF,FF00FF");
240  color_range_map expected;
241 
242  for(std::size_t i = 0; i < old_palette.size() && i < new_palette.size(); ++i) {
243  environment_setup env_setup;
244 
245  expected[old_palette[i]] = new_palette[i];
246  }
247 
248  BOOST_CHECK(expected == mod->map());
249 }
250 
251 /** Tests if the PAL modification with invalid arguments is ignored */
252 BOOST_AUTO_TEST_CASE(test_pal_modification_decoding_invalid_args)
253 {
254  environment_setup env_setup;
255 
256  modification_queue queue =
257  modification::decode("~PAL()~PAL(>)");
258 
259  BOOST_REQUIRE_EQUAL(queue.size(), 0);
260 }
261 
262 /** Tests if the FL modification is correctly decoded without arguments */
263 BOOST_AUTO_TEST_CASE(test_fl_modification_decoding_default)
264 {
265  environment_setup env_setup;
266 
267  modification_queue queue = modification::decode("~FL()");
268 
269  BOOST_REQUIRE_EQUAL(queue.size(), 1);
270 
271  fl_modification* mod = dynamic_cast<fl_modification*>(queue.top());
272 
273  // The dynamic_cast returns nullptr if the argument doesn't match the type
274  BOOST_REQUIRE(mod != nullptr);
275 
276  BOOST_CHECK(mod->get_horiz());
277  BOOST_CHECK(!mod->get_vert());
278 }
279 
280 /** Tests if the FL modification is correctly decoded with the horiz argument */
281 BOOST_AUTO_TEST_CASE(test_fl_modification_decoding_horiz)
282 {
283  environment_setup env_setup;
284 
285  modification_queue queue = modification::decode("~FL(horiz)");
286 
287  BOOST_REQUIRE_EQUAL(queue.size(), 1);
288 
289  fl_modification* mod = dynamic_cast<fl_modification*>(queue.top());
290 
291  // The dynamic_cast returns nullptr if the argument doesn't match the type
292  BOOST_REQUIRE(mod != nullptr);
293 
294  BOOST_CHECK(mod->get_horiz());
295  BOOST_CHECK(!mod->get_vert());
296 }
297 
298 /** Tests if the FL modification is correctly decoded with the vert argument */
299 BOOST_AUTO_TEST_CASE(test_fl_modification_decoding_vert)
300 {
301  environment_setup env_setup;
302 
303  modification_queue queue = modification::decode("~FL(vert)");
304 
305  BOOST_REQUIRE_EQUAL(queue.size(), 1);
306 
307  fl_modification* mod = dynamic_cast<fl_modification*>(queue.top());
308 
309  // The dynamic_cast returns nullptr if the argument doesn't match the type
310  BOOST_REQUIRE(mod != nullptr);
311 
312  BOOST_CHECK(!mod->get_horiz());
313  BOOST_CHECK(mod->get_vert());
314 }
315 
316 /** Tests if the FL modification is correctly decoded with both horiz and vert */
317 BOOST_AUTO_TEST_CASE(test_fl_modification_decoding_horiz_and_vert)
318 {
319  environment_setup env_setup;
320 
321  modification_queue queue = modification::decode("~FL(horiz,vert)");
322 
323  BOOST_REQUIRE_EQUAL(queue.size(), 1);
324 
325  fl_modification* mod = dynamic_cast<fl_modification*>(queue.top());
326 
327  // The dynamic_cast returns nullptr if the argument doesn't match the type
328  BOOST_REQUIRE(mod != nullptr);
329 
330  BOOST_CHECK(mod->get_horiz());
331  BOOST_CHECK(mod->get_vert());
332 }
333 
334 /** Tests if the GS modification is correctly decoded */
335 BOOST_AUTO_TEST_CASE(test_gs_modification_decoding)
336 {
337  environment_setup env_setup;
338 
339  modification_queue queue = modification::decode("~GS()");
340 
341  BOOST_REQUIRE(queue.size() == 1);
342 
343  gs_modification* mod = dynamic_cast<gs_modification*>(queue.top());
344 
345  // The dynamic_cast returns nullptr if the argument doesn't match the type
346  BOOST_CHECK(mod != nullptr);
347 }
348 
349 /** Tests if the CROP modification without arguments is ignored */
350 BOOST_AUTO_TEST_CASE(test_crop_modification_decoding_no_args)
351 {
352  environment_setup env_setup;
353 
354  modification_queue queue = modification::decode("~CROP()");
355 
356  BOOST_REQUIRE_EQUAL(queue.size(), 0);
357 }
358 
359 /** Tests if the CROP modification is correctly decoded when given one argument */
360 BOOST_AUTO_TEST_CASE(test_crop_modification_decoding_1_arg)
361 {
362  environment_setup env_setup;
363 
364  modification_queue queue = modification::decode("~CROP(1)");
365 
366  BOOST_REQUIRE_EQUAL(queue.size(), 1);
367 
368  crop_modification* mod = dynamic_cast<crop_modification*>(queue.top());
369 
370  // The dynamic_cast returns nullptr if the argument doesn't match the type
371  BOOST_REQUIRE(mod != nullptr);
372 
373  const SDL_Rect& slice = mod->get_slice();
374 
375  BOOST_CHECK_EQUAL(slice.x, 1);
376  BOOST_CHECK_EQUAL(slice.y, 0);
377  BOOST_CHECK_EQUAL(slice.w, 0);
378  BOOST_CHECK_EQUAL(slice.h, 0);
379 }
380 
381 /** Tests if the CROP modification is correctly decoded when given two args */
382 BOOST_AUTO_TEST_CASE(test_crop_modification_decoding_2_args)
383 {
384  environment_setup env_setup;
385 
386  modification_queue queue = modification::decode("~CROP(1,2)");
387 
388  BOOST_REQUIRE_EQUAL(queue.size(), 1);
389 
390  crop_modification* mod = dynamic_cast<crop_modification*>(queue.top());
391 
392  // The dynamic_cast returns nullptr if the argument doesn't match the type
393  BOOST_REQUIRE(mod != nullptr);
394 
395  const SDL_Rect& slice = mod->get_slice();
396 
397  BOOST_CHECK_EQUAL(slice.x, 1);
398  BOOST_CHECK_EQUAL(slice.y, 2);
399  BOOST_CHECK_EQUAL(slice.w, 0);
400  BOOST_CHECK_EQUAL(slice.h, 0);
401 }
402 
403 /** Tests if the CROP modification is correctly decoded when given three args */
404 BOOST_AUTO_TEST_CASE(test_crop_modification_decoding_3_args)
405 {
406  environment_setup env_setup;
407 
408  modification_queue queue = modification::decode("~CROP(1,2,3)");
409 
410  BOOST_REQUIRE_EQUAL(queue.size(), 1);
411 
412  crop_modification* mod = dynamic_cast<crop_modification*>(queue.top());
413 
414  // The dynamic_cast returns nullptr if the argument doesn't match the type
415  BOOST_REQUIRE(mod != nullptr);
416 
417  const SDL_Rect& slice = mod->get_slice();
418 
419  BOOST_CHECK_EQUAL(slice.x, 1);
420  BOOST_CHECK_EQUAL(slice.y, 2);
421  BOOST_CHECK_EQUAL(slice.w, 3);
422  BOOST_CHECK_EQUAL(slice.h, 0);
423 }
424 
425 /** Tests if the CROP modification is correctly decoded when given four args */
426 BOOST_AUTO_TEST_CASE(test_crop_modification_decoding_4_args)
427 {
428  environment_setup env_setup;
429 
430  modification_queue queue = modification::decode("~CROP(1,2,3,4)");
431 
432  BOOST_REQUIRE_EQUAL(queue.size(), 1);
433 
434  crop_modification* mod = dynamic_cast<crop_modification*>(queue.top());
435 
436  // The dynamic_cast returns nullptr if the argument doesn't match the type
437  BOOST_REQUIRE(mod != nullptr);
438 
439  const SDL_Rect& slice = mod->get_slice();
440 
441  BOOST_CHECK_EQUAL(slice.x, 1);
442  BOOST_CHECK_EQUAL(slice.y, 2);
443  BOOST_CHECK_EQUAL(slice.w, 3);
444  BOOST_CHECK_EQUAL(slice.h, 4);
445 }
446 
447 /** Tests if the BLIT modification with one argument is correctly decoded
448  *
449  * @todo check if the surface is correct
450  */
451 BOOST_AUTO_TEST_CASE(test_blit_modification_decoding_1_arg)
452 {
453  environment_setup env_setup;
454 
455  modification_queue queue = modification::decode("~BLIT(wesnoth-icon.png)");
456 
457  BOOST_REQUIRE_EQUAL(queue.size(), 1);
458 
459  blit_modification* mod = dynamic_cast<blit_modification*>(queue.top());
460 
461  // The dynamic_cast returns nullptr if the argument doesn't match the type
462  BOOST_REQUIRE(mod != nullptr);
463 
464  BOOST_CHECK(mod->get_surface());
465  BOOST_CHECK_EQUAL(mod->get_x(), 0);
466  BOOST_CHECK_EQUAL(mod->get_y(), 0);
467 }
468 
469 /** Tests if the BLIT modification with three arguments is correctly decoded
470  *
471  * @todo check if the surface is correct
472  */
473 BOOST_AUTO_TEST_CASE(test_blit_modification_decoding_3_args)
474 {
475  environment_setup env_setup;
476 
477  modification_queue queue = modification::decode("~BLIT(wesnoth-icon.png,1,2)");
478 
479  BOOST_REQUIRE_EQUAL(queue.size(), 1);
480 
481  blit_modification* mod = dynamic_cast<blit_modification*>(queue.top());
482 
483  BOOST_REQUIRE(mod != nullptr);
484  // The dynamic_cast returns nullptr if the argument doesn't match the type
485 
486  BOOST_CHECK(mod->get_surface());
487  BOOST_CHECK_EQUAL(mod->get_x(), 1);
488  BOOST_CHECK_EQUAL(mod->get_y(), 2);
489 }
490 
491 /** Tests if the BLIT modification with invalid arguments is ignored */
492 BOOST_AUTO_TEST_CASE(test_blit_modification_decoding_invalid_args)
493 {
494  environment_setup env_setup;
495 
496  modification_queue queue =
497  modification::decode("~BLIT()"
498  "~BLIT(wesnoth-icon.png,1,-2)"
499  "~BLIT(wesnoth-icon.png,-1,2)"
500  "~BLIT(wesnoth-icon.png,-1,-2)"
501  "~BLIT(wesnoth-icon.png,1,2,3)");
502 
503  BOOST_CHECK_EQUAL(queue.size(), 3);
504 }
505 
506 /** Tests if the MASK modification with one argument is correctly decoded
507  *
508  * @todo check if the surface is correct
509  */
510 BOOST_AUTO_TEST_CASE(test_mask_modification_decoding_1_arg)
511 {
512  environment_setup env_setup;
513 
514  modification_queue queue = modification::decode("~MASK(wesnoth-icon.png)");
515 
516  BOOST_REQUIRE_EQUAL(queue.size(), 1);
517 
518  mask_modification* mod = dynamic_cast<mask_modification*>(queue.top());
519 
520  // The dynamic_cast returns nullptr if the argument doesn't match the type
521  BOOST_REQUIRE(mod != nullptr);
522 
523  BOOST_CHECK(mod->get_mask());
524  BOOST_CHECK_EQUAL(mod->get_x(), 0);
525  BOOST_CHECK_EQUAL(mod->get_y(), 0);
526 }
527 
528 /** Tests if the MASK modification with three arguments is correctly decoded
529  *
530  * @todo check if the surface is correct
531  */
532 BOOST_AUTO_TEST_CASE(test_mask_modification_decoding_3_args)
533 {
534  environment_setup env_setup;
535 
536  modification_queue queue = modification::decode("~MASK(wesnoth-icon.png,3,4)");
537 
538  BOOST_REQUIRE_EQUAL(queue.size(), 1);
539 
540  mask_modification* mod = dynamic_cast<mask_modification*>(queue.top());
541 
542  // The dynamic_cast returns nullptr if the argument doesn't match the type
543  BOOST_REQUIRE(mod != nullptr);
544 
545  BOOST_CHECK(mod->get_mask());
546  BOOST_CHECK_EQUAL(mod->get_x(), 3);
547  BOOST_CHECK_EQUAL(mod->get_y(), 4);
548 }
549 
550 /** Tests if the MASK modification with invalid arguments is ignored */
551 BOOST_AUTO_TEST_CASE(test_mask_modification_decoding_invalid_args)
552 {
553  environment_setup env_setup;
554 
555  modification_queue queue =
556  modification::decode("~MASK()"
557  "~MASK(wesnoth-icon.png,3,-4)"
558  "~MASK(wesnoth-icon.png,-3,4)"
559  "~MASK(wesnoth-icon.png,-3,-4)");
560 
561  BOOST_CHECK_EQUAL(queue.size(), 0);
562 }
563 
564 /** Tests if the L modification without arguments is ignored */
565 BOOST_AUTO_TEST_CASE(test_l_modification_decoding_no_args)
566 {
567  environment_setup env_setup;
568 
570 
571  BOOST_CHECK_EQUAL(queue.size(), 0);
572 }
573 
574 /** Tests if the L modification with one argument is correctly decoded
575  *
576  * @todo check if the surface is correct
577  */
578 BOOST_AUTO_TEST_CASE(test_l_modification_decoding_1_arg)
579 {
580  environment_setup env_setup;
581 
582  modification_queue queue = modification::decode("~L(wesnoth-icon.png)");
583 
584  BOOST_REQUIRE_EQUAL(queue.size(), 1);
585 
586  light_modification* mod = dynamic_cast<light_modification*>(queue.top());
587 
588  // The dynamic_cast returns nullptr if the argument doesn't match the type
589  BOOST_REQUIRE(mod != nullptr);
590 
591  BOOST_CHECK(mod->get_surface());
592 }
593 
594 /** Tests if the SCALE modification without arguments is ignored */
595 BOOST_AUTO_TEST_CASE(test_scale_modification_decoding_no_args)
596 {
597  environment_setup env_setup;
598 
599  modification_queue queue = modification::decode("~SCALE()");
600 
601  BOOST_CHECK_EQUAL(queue.size(), 0);
602 }
603 
604 /** Tests if the SCALE modification with one argument is correctly decoded */
605 BOOST_AUTO_TEST_CASE(test_scale_modification_decoding_1_arg)
606 {
607  environment_setup env_setup;
608 
609  modification_queue queue = modification::decode("~SCALE(3)");
610 
611  BOOST_REQUIRE_EQUAL(queue.size(), 1);
612 
613  scale_modification* mod = dynamic_cast<scale_modification*>(queue.top());
614 
615  // The dynamic_cast returns nullptr if the argument doesn't match the type
616  BOOST_REQUIRE(mod != nullptr);
617 
618  BOOST_CHECK_EQUAL(mod->get_w(), 3);
619  BOOST_CHECK_EQUAL(mod->get_h(), 0);
620 }
621 
622 /** Tests if the SCALE modification with two arguments is correctly decoded */
623 BOOST_AUTO_TEST_CASE(test_scale_modification_decoding_2_args)
624 {
625  environment_setup env_setup;
626 
627  modification_queue queue = modification::decode("~SCALE(4,5)");
628 
629  BOOST_REQUIRE_EQUAL(queue.size(), 1);
630 
631  scale_modification* mod = dynamic_cast<scale_modification*>(queue.top());
632 
633  // The dynamic_cast returns nullptr if the argument doesn't match the type
634  BOOST_REQUIRE(mod != nullptr);
635 
636  BOOST_CHECK_EQUAL(mod->get_w(), 4);
637  BOOST_CHECK_EQUAL(mod->get_h(), 5);
638 }
639 
640 /** Tests if the O modification with a percent argument is correctly decoded */
641 BOOST_AUTO_TEST_CASE(test_o_modification_decoding_percent_args)
642 {
643  environment_setup env_setup;
644 
645  modification_queue queue = modification::decode("~O(45%)");
646 
647  BOOST_REQUIRE_EQUAL(queue.size(), 1);
648 
649  o_modification* mod = dynamic_cast<o_modification*>(queue.top());
650 
651  // The dynamic_cast returns nullptr if the argument doesn't match the type
652  BOOST_REQUIRE(mod != nullptr);
653 
654  BOOST_CHECK(mod->get_opacity() > 0.44f);
655  BOOST_CHECK(mod->get_opacity() < 0.46f);
656 }
657 
658 /** Tests if the O modification with a fraction argument is correctly decoded */
659 BOOST_AUTO_TEST_CASE(test_o_modification_decoding_fraction_args)
660 {
661  environment_setup env_setup;
662 
663  modification_queue queue = modification::decode("~O(0.34)");
664 
665  BOOST_REQUIRE_EQUAL(queue.size(), 1);
666 
667  o_modification* mod = dynamic_cast<o_modification*>(queue.top());
668 
669  // The dynamic_cast returns nullptr if the argument doesn't match the type
670  BOOST_REQUIRE(mod != nullptr);
671 
672  BOOST_CHECK(mod->get_opacity() > 0.33f);
673  BOOST_CHECK(mod->get_opacity() < 0.35f);
674 }
675 
676 /** Tests if the BL modification without arguments is correctly decoded */
677 BOOST_AUTO_TEST_CASE(test_bl_modification_decoding_no_args)
678 {
679  environment_setup env_setup;
680 
681  modification_queue queue = modification::decode("~BL()");
682 
683  BOOST_REQUIRE_EQUAL(queue.size(), 1);
684 
685  bl_modification* mod = dynamic_cast<bl_modification*>(queue.top());
686 
687  // The dynamic_cast returns nullptr if the argument doesn't match the type
688  BOOST_REQUIRE(mod != nullptr);
689 
690  BOOST_CHECK_EQUAL(mod->get_depth(), 0);
691 }
692 
693 /** Tests if the BL modification with one argument is correctly decoded */
694 BOOST_AUTO_TEST_CASE(test_bl_modification_decoding)
695 {
696  environment_setup env_setup;
697 
698  modification_queue queue = modification::decode("~BL(2)");
699 
700  BOOST_REQUIRE_EQUAL(queue.size(), 1);
701 
702  bl_modification* mod = dynamic_cast<bl_modification*>(queue.top());
703 
704  // The dynamic_cast returns nullptr if the argument doesn't match the type
705  BOOST_REQUIRE(mod != nullptr);
706 
707  BOOST_CHECK_EQUAL(mod->get_depth(), 2);
708 }
709 
710 /** Tests if the R, G and B modifications without args are correctly decoded */
711 BOOST_AUTO_TEST_CASE(test_rgb_modification_decoding_no_args)
712 {
713  environment_setup env_setup;
714 
715  modification_queue queue = modification::decode("~R()~G()~B()");
716 
717  BOOST_REQUIRE_EQUAL(queue.size(), 3);
718 
719  for(int i = 0; i < 3; i++) {
720  environment_setup env_setup;
721 
722  cs_modification* mod = dynamic_cast<cs_modification*>(queue.top());
723 
724  // The dynamic_cast returns nullptr if the argument doesn't match the type
725  BOOST_REQUIRE(mod != nullptr);
726 
727  BOOST_CHECK_EQUAL(mod->get_r(), 0);
728  BOOST_CHECK_EQUAL(mod->get_g(), 0);
729  BOOST_CHECK_EQUAL(mod->get_b(), 0);
730 
731  queue.pop();
732  }
733 }
734 
735 /** Tests if the R modification with one argument is correctly decoded */
736 BOOST_AUTO_TEST_CASE(test_r_modification_decoding)
737 {
738  environment_setup env_setup;
739 
740  modification_queue queue = modification::decode("~R(123)");
741 
742  BOOST_REQUIRE_EQUAL(queue.size(), 1);
743 
744  cs_modification* mod = dynamic_cast<cs_modification*>(queue.top());
745 
746  // The dynamic_cast returns nullptr if the argument doesn't match the type
747  BOOST_REQUIRE(mod != nullptr);
748 
749  BOOST_CHECK_EQUAL(mod->get_r(), 123);
750  BOOST_CHECK_EQUAL(mod->get_g(), 0);
751  BOOST_CHECK_EQUAL(mod->get_b(), 0);
752 }
753 
754 /** Tests if the G modification with one argument is correctly decoded */
755 BOOST_AUTO_TEST_CASE(test_g_modification_decoding)
756 {
757  environment_setup env_setup;
758 
759  modification_queue queue = modification::decode("~G(132)");
760 
761  BOOST_REQUIRE_EQUAL(queue.size(), 1);
762 
763  cs_modification* mod = dynamic_cast<cs_modification*>(queue.top());
764 
765  // The dynamic_cast returns nullptr if the argument doesn't match the type
766  BOOST_REQUIRE(mod != nullptr);
767 
768  BOOST_CHECK_EQUAL(mod->get_r(), 0);
769  BOOST_CHECK_EQUAL(mod->get_g(), 132);
770  BOOST_CHECK_EQUAL(mod->get_b(), 0);
771 }
772 
773 /** Tests if the B modification with one argument is correctly decoded */
774 BOOST_AUTO_TEST_CASE(test_b_modification_decoding)
775 {
776  environment_setup env_setup;
777 
778  modification_queue queue = modification::decode("~B(312)");
779 
780  BOOST_REQUIRE_EQUAL(queue.size(), 1);
781 
782  cs_modification* mod = dynamic_cast<cs_modification*>(queue.top());
783 
784  // The dynamic_cast returns nullptr if the argument doesn't match the type
785  BOOST_REQUIRE(mod != nullptr);
786 
787  BOOST_CHECK_EQUAL(mod->get_r(), 0);
788  BOOST_CHECK_EQUAL(mod->get_g(), 0);
789  BOOST_CHECK_EQUAL(mod->get_b(), 312);
790 }
791 
792 /** Tests if the BG modification without arguments is correctly decoded */
793 BOOST_AUTO_TEST_CASE(test_bg_modification_decoding_no_args)
794 {
795  environment_setup env_setup;
796 
797  modification_queue queue = modification::decode("~BG()");
798 
799  BOOST_REQUIRE_EQUAL(queue.size(), 1);
800 
801  background_modification* mod = dynamic_cast<background_modification*>(queue.top());
802 
803  // The dynamic_cast returns nullptr if the argument doesn't match the type
804  BOOST_REQUIRE(mod != nullptr);
805 
806  BOOST_CHECK_EQUAL(mod->get_color().r, 0);
807  BOOST_CHECK_EQUAL(mod->get_color().g, 0);
808  BOOST_CHECK_EQUAL(mod->get_color().b, 0);
809  BOOST_CHECK_EQUAL(mod->get_color().a, SDL_ALPHA_OPAQUE);
810 }
811 
812 /** Tests if the BG modification with one argument is correctly decoded */
813 BOOST_AUTO_TEST_CASE(test_bg_modification_decoding_1_arg)
814 {
815  environment_setup env_setup;
816 
817  modification_queue queue = modification::decode("~BG(1)");
818 
819  BOOST_REQUIRE_EQUAL(queue.size(), 1);
820 
821  background_modification* mod = dynamic_cast<background_modification*>(queue.top());
822 
823  // The dynamic_cast returns nullptr if the argument doesn't match the type
824  BOOST_REQUIRE(mod != nullptr);
825 
826  BOOST_CHECK_EQUAL(mod->get_color().r, 1);
827  BOOST_CHECK_EQUAL(mod->get_color().g, 0);
828  BOOST_CHECK_EQUAL(mod->get_color().b, 0);
829  BOOST_CHECK_EQUAL(mod->get_color().a, SDL_ALPHA_OPAQUE);
830 }
831 
832 /** Tests if the BG modification with two arguments is correctly decoded */
833 BOOST_AUTO_TEST_CASE(test_bg_modification_decoding_2_args)
834 {
835  environment_setup env_setup;
836 
837  modification_queue queue = modification::decode("~BG(1,2)");
838 
839  BOOST_REQUIRE_EQUAL(queue.size(), 1);
840 
841  background_modification* mod = dynamic_cast<background_modification*>(queue.top());
842 
843  // The dynamic_cast returns nullptr if the argument doesn't match the type
844  BOOST_REQUIRE(mod != nullptr);
845 
846  BOOST_CHECK_EQUAL(mod->get_color().r, 1);
847  BOOST_CHECK_EQUAL(mod->get_color().g, 2);
848  BOOST_CHECK_EQUAL(mod->get_color().b, 0);
849  BOOST_CHECK_EQUAL(mod->get_color().a, SDL_ALPHA_OPAQUE);
850 }
851 
852 /** Tests if the BG modification with three arguments is correctly decoded */
853 BOOST_AUTO_TEST_CASE(test_bg_modification_decoding_3_args)
854 {
855  environment_setup env_setup;
856 
857  modification_queue queue = modification::decode("~BG(1,2,3)");
858 
859  BOOST_REQUIRE_EQUAL(queue.size(), 1);
860 
861  background_modification* mod = dynamic_cast<background_modification*>(queue.top());
862 
863  // The dynamic_cast returns nullptr if the argument doesn't match the type
864  BOOST_REQUIRE(mod != nullptr);
865 
866  BOOST_CHECK_EQUAL(mod->get_color().r, 1);
867  BOOST_CHECK_EQUAL(mod->get_color().g, 2);
868  BOOST_CHECK_EQUAL(mod->get_color().b, 3);
869  BOOST_CHECK_EQUAL(mod->get_color().a, SDL_ALPHA_OPAQUE);
870 }
871 
872 /** Tests if the BG modification with four arguments is correctly decoded */
873 BOOST_AUTO_TEST_CASE(test_bg_modification_decoding_4_args)
874 {
875  environment_setup env_setup;
876 
877  modification_queue queue = modification::decode("~BG(1,2,3,4)");
878 
879  BOOST_REQUIRE_EQUAL(queue.size(), 1);
880 
881  background_modification* mod = dynamic_cast<background_modification*>(queue.top());
882 
883  // The dynamic_cast returns nullptr if the argument doesn't match the type
884  BOOST_REQUIRE(mod != nullptr);
885 
886  BOOST_CHECK_EQUAL(mod->get_color().r, 1);
887  BOOST_CHECK_EQUAL(mod->get_color().g, 2);
888  BOOST_CHECK_EQUAL(mod->get_color().b, 3);
889  BOOST_CHECK_EQUAL(mod->get_color().a, 4);
890 }
891 
892 BOOST_AUTO_TEST_SUITE_END()
A color range definition is made of four reference RGB colors, used for calculating conversions from ...
Definition: color_range.hpp:49
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
config & add_child(config_key_type key)
Definition: config.cpp:441
A class grating read only view to a vector of config objects, viewed as one config with all children ...
static game_config_view wrap(const config &cfg)
Gaussian-like blur (BL) modification.
Scale (BLIT) modification.
const surface & get_surface() const
Crop (CROP) modification.
const SDL_Rect & get_slice() const
Color-shift (CS, R, G, B) modification.
Mirror (FL) modification.
Grayscale (GS) modification.
LIGHT (L) modification.
const surface & get_surface() const
Mask (MASK) modification.
const surface & get_mask() const
A modified priority queue used to order image modifications.
modification * top() const
Returns the top element in the queue .
void pop()
Removes the top element from the queue.
void push(std::unique_ptr< modification > mod)
Adds mod to the queue (unless mod is nullptr).
std::size_t size() const
Returns the number of elements in the queue.
Base abstract class for an image-path modification.
static modification_queue decode(const std::string &)
Decodes modifications from a modification string.
Opacity (O) modification.
Recolor (RC/TC/PAL) modification.
const color_range_map & map() const
Scaling (SCALE[_INTO], SCALE[_INTO]_SHARP) modifications.
Helper class to redirect the output of the logger in a certain scope.
Definition: log.hpp:98
color_range_map recolor_range(const color_range &new_range, const std::vector< color_t > &old_rgb)
Converts a source palette using the specified color_range object.
Definition: color_range.cpp:29
std::unordered_map< color_t, color_t > color_range_map
Definition: color_range.hpp:30
Declarations for File-IO.
std::size_t i
Definition: function.cpp:968
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:207
Standard logging facilities (interface).
std::string path
Definition: filesystem.cpp:83
const std::vector< color_t > & tc_info(std::string_view name)
const color_range & color_info(std::string_view name)
static void add_color_info(const game_config_view &v, bool build_defaults)
Functions to load and save images from/to disk.
The paths manager is responsible for recording the various paths that binary files may be located at.
Definition: filesystem.hpp:398
Fill background with a color (BG).
BOOST_AUTO_TEST_SUITE(filesystem)
BOOST_AUTO_TEST_CASE(test_modificaiton_queue_order)
Tests if modifications with a higher priority are placed before the others.