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