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