source: libcaca/trunk/tests/dirty.cpp @ 3907

Last change on this file since 3907 was 3579, checked in by Sam Hocevar, 14 years ago

Add unit tests for efficient dirty rectangle merging.

  • Property svn:keywords set to Id
File size: 9.3 KB
Line 
1/*
2 *  caca-test     testsuite program for libcaca
3 *  Copyright (c) 2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id: dirty.cpp 3579 2009-07-26 16:20:20Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16
17#include <cppunit/extensions/HelperMacros.h>
18#include <cppunit/TestCaller.h>
19#include <cppunit/TestCase.h>
20#include <cppunit/TestSuite.h>
21
22#include "caca.h"
23
24class DirtyTest : public CppUnit::TestCase
25{
26    CPPUNIT_TEST_SUITE(DirtyTest);
27    CPPUNIT_TEST(test_create);
28    CPPUNIT_TEST(test_put_char_dirty);
29    CPPUNIT_TEST(test_put_char_not_dirty);
30    CPPUNIT_TEST(test_simplify);
31    CPPUNIT_TEST(test_box);
32    CPPUNIT_TEST(test_blit);
33    CPPUNIT_TEST_SUITE_END();
34
35public:
36    DirtyTest() : CppUnit::TestCase("Dirty Rectangles Test") {}
37
38    void setUp() {}
39
40    void tearDown() {}
41
42    void test_create()
43    {
44        caca_canvas_t *cv;
45        int dx, dy, dw, dh;
46
47        /* Check that we only have one dirty rectangle upon creation. */
48        cv = caca_create_canvas(WIDTH, HEIGHT);
49        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
50
51        /* Check that our only rectangle contains the whole canvas. */
52        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
53        CPPUNIT_ASSERT_EQUAL(0, dx);
54        CPPUNIT_ASSERT_EQUAL(0, dy);
55        CPPUNIT_ASSERT_EQUAL(WIDTH, dw);
56        CPPUNIT_ASSERT_EQUAL(HEIGHT, dh);
57
58        /* Invalidate the dirty rectangle and check that it stays so. */
59        caca_clear_dirty_rect_list(cv);
60        CPPUNIT_ASSERT_EQUAL(0, caca_get_dirty_rect_count(cv));
61
62        caca_free_canvas(cv);
63    }
64
65    void test_put_char_dirty()
66    {
67        caca_canvas_t *cv;
68        int dx, dy, dw, dh;
69
70        cv = caca_create_canvas(WIDTH, HEIGHT);
71
72        /* Check that one character creates a 1x1 dirty rect. */
73        caca_clear_dirty_rect_list(cv);
74        caca_put_char(cv, 7, 3, 'x');
75
76        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
77        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
78        CPPUNIT_ASSERT_EQUAL(7, dx);
79        CPPUNIT_ASSERT_EQUAL(3, dy);
80        CPPUNIT_ASSERT_EQUAL(1, dw);
81        CPPUNIT_ASSERT_EQUAL(1, dh);
82
83        /* Check that a fullwidth character creates a 2x1 dirty rect. */
84        caca_clear_canvas(cv);
85        caca_clear_dirty_rect_list(cv);
86        caca_put_char(cv, 7, 3, 0x2f06 /* ⼆ */);
87
88        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
89        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
90        CPPUNIT_ASSERT_EQUAL(7, dx);
91        CPPUNIT_ASSERT_EQUAL(3, dy);
92        CPPUNIT_ASSERT_EQUAL(2, dw);
93        CPPUNIT_ASSERT_EQUAL(1, dh);
94
95        /* Check that a character over a fullwidth character creates a
96         * 2x1 dirty rect because of clobbering on the left side. */
97        caca_clear_canvas(cv);
98        caca_put_char(cv, 7, 3, 0x2f06 /* ⼆ */);
99        caca_clear_dirty_rect_list(cv);
100        caca_put_char(cv, 7, 3, 'x');
101
102        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
103        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
104        CPPUNIT_ASSERT_EQUAL(7, dx);
105        CPPUNIT_ASSERT_EQUAL(3, dy);
106        CPPUNIT_ASSERT_EQUAL(2, dw);
107        CPPUNIT_ASSERT_EQUAL(1, dh);
108
109        /* Check that a character over a fullwidth character creates a
110         * 2x1 dirty rect because of clobbering on the right side. */
111        caca_clear_canvas(cv);
112        caca_put_char(cv, 7, 3, 0x2f06 /* ⼆ */);
113        caca_clear_dirty_rect_list(cv);
114        caca_put_char(cv, 8, 3, 'x');
115
116        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
117        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
118        CPPUNIT_ASSERT_EQUAL(7, dx);
119        CPPUNIT_ASSERT_EQUAL(3, dy);
120        CPPUNIT_ASSERT_EQUAL(2, dw);
121        CPPUNIT_ASSERT_EQUAL(1, dh);
122
123        /* Check that a fullwidth character over a fullwidth character creates
124         * a 3x1 dirty rect because of clobbering on the left side. */
125        caca_clear_canvas(cv);
126        caca_put_char(cv, 7, 3, 0x2f06 /* ⼆ */);
127        caca_clear_dirty_rect_list(cv);
128        caca_put_char(cv, 6, 3, 0x2f06 /* ⼆ */);
129
130        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
131        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
132        CPPUNIT_ASSERT_EQUAL(6, dx);
133        CPPUNIT_ASSERT_EQUAL(3, dy);
134        CPPUNIT_ASSERT_EQUAL(3, dw);
135        CPPUNIT_ASSERT_EQUAL(1, dh);
136
137        /* Check that a fullwidth character over a fullwidth character creates
138         * a 3x1 dirty rect because of clobbering on the right side. */
139        caca_clear_canvas(cv);
140        caca_put_char(cv, 7, 3, 0x2f06 /* ⼆ */);
141        caca_clear_dirty_rect_list(cv);
142        caca_put_char(cv, 8, 3, 0x2f06 /* ⼆ */);
143
144        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
145        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
146        CPPUNIT_ASSERT_EQUAL(7, dx);
147        CPPUNIT_ASSERT_EQUAL(3, dy);
148        CPPUNIT_ASSERT_EQUAL(3, dw);
149        CPPUNIT_ASSERT_EQUAL(1, dh);
150    }
151
152    void test_put_char_not_dirty()
153    {
154        caca_canvas_t *cv;
155
156        cv = caca_create_canvas(WIDTH, HEIGHT);
157
158        /* Check that pasting the same character does not cause a dirty
159         * rectangle to be created. */
160        caca_put_char(cv, 7, 3, 'x');
161        caca_clear_dirty_rect_list(cv);
162        caca_put_char(cv, 7, 3, 'x');
163
164        CPPUNIT_ASSERT_EQUAL(0, caca_get_dirty_rect_count(cv));
165
166        /* Check that pasting the same fullwidth character does not cause
167         * a dirty rectangle to be created. */
168        caca_clear_canvas(cv);
169        caca_put_char(cv, 7, 3, 0x2f06 /* ⼆ */);
170        caca_clear_dirty_rect_list(cv);
171        caca_put_char(cv, 7, 3, 0x2f06 /* ⼆ */);
172
173        CPPUNIT_ASSERT_EQUAL(0, caca_get_dirty_rect_count(cv));
174    }
175
176    void test_simplify()
177    {
178        caca_canvas_t *cv;
179        int dx, dy, dw, dh;
180
181        cv = caca_create_canvas(WIDTH, HEIGHT);
182
183        /* Check that N adjacent blits only create one dirty rectangle */
184        caca_clear_dirty_rect_list(cv);
185        for(int i = 0; i < 10; i++)
186        {
187            caca_put_char(cv, 7 + i, 3, '-');
188
189            CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
190            caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
191            CPPUNIT_ASSERT_EQUAL(7, dx);
192            CPPUNIT_ASSERT_EQUAL(3, dy);
193            CPPUNIT_ASSERT_EQUAL(1 + i, dw);
194            CPPUNIT_ASSERT_EQUAL(1, dh);
195        }
196
197        /* Check that N adjacent blits only create one dirty rectangle */
198        caca_clear_dirty_rect_list(cv);
199        for(int j = 0; j < 10; j++)
200        {
201            caca_put_char(cv, 7, 3 + j, '|');
202
203            CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
204            caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
205            CPPUNIT_ASSERT_EQUAL(7, dx);
206            CPPUNIT_ASSERT_EQUAL(3, dy);
207            CPPUNIT_ASSERT_EQUAL(1, dw);
208            CPPUNIT_ASSERT_EQUAL(1 + j, dh);
209        }
210    }
211
212    void test_box()
213    {
214        caca_canvas_t *cv;
215        int dx, dy, dw, dh;
216
217        cv = caca_create_canvas(WIDTH, HEIGHT);
218        caca_clear_dirty_rect_list(cv);
219
220        /* Check that a filled box creates one dirty rectangle of the same
221         * size. */
222        caca_fill_box(cv, 7, 3, 14, 9, 'x');
223
224        CPPUNIT_ASSERT_EQUAL(1, caca_get_dirty_rect_count(cv));
225        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
226        CPPUNIT_ASSERT_EQUAL(7, dx);
227        CPPUNIT_ASSERT_EQUAL(3, dy);
228        CPPUNIT_ASSERT_EQUAL(14, dw);
229        CPPUNIT_ASSERT_EQUAL(9, dh);
230
231        /* Check that the same filled box does not create a new dirty
232         * rectangle. */
233        caca_clear_dirty_rect_list(cv);
234        caca_fill_box(cv, 7, 3, 14, 9, 'x');
235
236        CPPUNIT_ASSERT_EQUAL(0, caca_get_dirty_rect_count(cv));
237    }
238
239    void test_blit()
240    {
241        caca_canvas_t *cv, *cv2;
242        int i, dx, dy, dw, dh;
243
244        cv = caca_create_canvas(WIDTH, HEIGHT);
245        caca_clear_dirty_rect_list(cv);
246        cv2 = caca_create_canvas(2, 2);
247        caca_fill_box(cv2, 0, 0, 2, 1, 'x');
248
249        /* Check that blitting a canvas make a dirty rectangle
250         * only for modified lines */
251        /* FIXME: check this test's validity */
252
253        caca_blit(cv, 1, 1, cv2, NULL);
254        i = caca_get_dirty_rect_count(cv);
255        CPPUNIT_ASSERT_EQUAL(1, i);
256        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
257
258        CPPUNIT_ASSERT(1 == dx);
259        CPPUNIT_ASSERT(1 == dy);
260        CPPUNIT_ASSERT(2 <= dw);
261        CPPUNIT_ASSERT(1 == dh);
262
263        caca_clear_canvas(cv);
264        caca_clear_dirty_rect_list(cv);
265
266        /* Check that blitting a canvas make a dirty rectangle
267         * only for modified chars when we have a mask */
268        /* FIXME: check this test's validity */
269
270        caca_blit(cv, 1, 1, cv2, cv2);
271        i = caca_get_dirty_rect_count(cv);
272        CPPUNIT_ASSERT_EQUAL(1, i);
273        caca_get_dirty_rect(cv, 0, &dx, &dy, &dw, &dh);
274
275        CPPUNIT_ASSERT(1 == dx);
276        CPPUNIT_ASSERT(1 == dy);
277        CPPUNIT_ASSERT(2 == dw);
278        CPPUNIT_ASSERT(1 == dh);
279
280        CPPUNIT_ASSERT(' ' == caca_get_char(cv, 0, 0));
281
282    }
283
284private:
285    static int const WIDTH, HEIGHT;
286};
287
288int const DirtyTest::WIDTH = 80;
289int const DirtyTest::HEIGHT = 50;
290
291CPPUNIT_TEST_SUITE_REGISTRATION(DirtyTest);
292
Note: See TracBrowser for help on using the repository browser.