1 // vim: ts=2 sw=2 et
2 /*
3  * These tests are of limited usefulness.  In fact, you might even say that
4  * they're not really tests at all.  But I felt that it would be useful to have
5  * some basic usage of most functions just to verify that things compile and
6  * work generally
7  */
8 
9 #include <cfloat>
10 #include <boost/test/unit_test.hpp>
11 #include <boost/test/test_tools.hpp>
12 #include <boost/test/floating_point_comparison.hpp>
13 using namespace boost::unit_test;
14 #include <cairomm/context.h>
15 #include <cairomm/scaledfont.h>
16 
17 #define CREATE_CONTEXT(varname) \
18   auto surf = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, 10, 10); \
19   auto cr = Cairo::Context::create(surf);
20 
21 void
test_dashes()22 test_dashes ()
23 {
24   CREATE_CONTEXT(cr);
25   std::valarray<double> dash_array(4);
26   dash_array[0] = 0.1;
27   dash_array[1] = 0.2;
28   dash_array[2] = 0.04;
29   dash_array[3] = 0.31;
30   cr->set_dash(dash_array, 0.54);
31 
32   std::vector<double> get_array;
33   double get_offset;
34   cr->get_dash (get_array, get_offset);
35   BOOST_CHECK_EQUAL (dash_array[0], get_array[0]);
36   BOOST_CHECK_EQUAL (dash_array[1], get_array[1]);
37   BOOST_CHECK_EQUAL (dash_array[2], get_array[2]);
38   BOOST_CHECK_EQUAL (dash_array[3], get_array[3]);
39   BOOST_CHECK_EQUAL (0.54, get_offset);
40 
41   std::vector<double> dash_vect(4);
42   dash_vect[0] = 0.5;
43   dash_vect[1] = 0.25;
44   dash_vect[2] = 0.93;
45   dash_vect[3] = 1.31;
46   cr->set_dash(dash_vect, 0.4);
47 
48   cr->get_dash (get_array, get_offset);
49   BOOST_CHECK_EQUAL (dash_vect[0], get_array[0]);
50   BOOST_CHECK_EQUAL (dash_vect[1], get_array[1]);
51   BOOST_CHECK_EQUAL (dash_vect[2], get_array[2]);
52   BOOST_CHECK_EQUAL (dash_vect[3], get_array[3]);
53   BOOST_CHECK_EQUAL (0.4, get_offset);
54 
55   cr->unset_dash ();
56   cr->get_dash (get_array, get_offset);
57   BOOST_CHECK (get_array.empty ());
58 }
59 
60 void
test_save_restore()61 test_save_restore ()
62 {
63   CREATE_CONTEXT(cr);
64   cr->set_line_width (2.3);
65   cr->save ();
66   cr->set_line_width (4.0);
67   BOOST_CHECK_EQUAL (4.0, cr->get_line_width ());
68   cr->restore ();
69   BOOST_CHECK_EQUAL (2.3, cr->get_line_width ());
70 }
71 
72 void
test_operator()73 test_operator ()
74 {
75   CREATE_CONTEXT(cr);
76   cr->set_operator (Cairo::OPERATOR_ATOP);
77   BOOST_CHECK_EQUAL (Cairo::OPERATOR_ATOP, cr->get_operator ());
78   cr->set_operator (Cairo::OPERATOR_CLEAR);
79   BOOST_CHECK_EQUAL (Cairo::OPERATOR_CLEAR, cr->get_operator ());
80 }
81 
82 void
test_source()83 test_source ()
84 {
85   CREATE_CONTEXT(cr);
86   auto solid_pattern =
87     Cairo::SolidPattern::create_rgb (1.0, 0.5, 0.25);
88   auto gradient_pattern =
89     Cairo::LinearGradient::create (0.0, 0.0, 1.0, 1.0);
90 
91   cr->set_source (solid_pattern);
92   {
93     auto retrieved_solid =
94       Cairo::RefPtr<Cairo::SolidPattern>::cast_dynamic(cr->get_source ());
95     BOOST_REQUIRE (retrieved_solid);
96     double r, g, b, a;
97     retrieved_solid->get_rgba (r, g, b, a);
98     BOOST_CHECK_EQUAL (1.0, r);
99     BOOST_CHECK_EQUAL (0.5, g);
100     BOOST_CHECK_EQUAL (0.25, b);
101 
102     // now try for const objects..
103     auto cr2 = cr;
104     auto retrieved_solid2 =
105       Cairo::RefPtr<const Cairo::SolidPattern>::cast_dynamic(cr2->get_source ());
106     BOOST_REQUIRE (retrieved_solid2);
107   }
108 
109   cr->set_source (gradient_pattern);
110   {
111     auto retrieved_linear =
112       Cairo::RefPtr<Cairo::LinearGradient>::cast_dynamic(cr->get_source ());
113     BOOST_REQUIRE (retrieved_linear);
114     double x0, x1, y0, y1;
115     retrieved_linear->get_linear_points (x0, y0, x1, y1);
116     BOOST_CHECK_EQUAL (0.0, x0);
117     BOOST_CHECK_EQUAL (0.0, y0);
118     BOOST_CHECK_EQUAL (1.0, x1);
119     BOOST_CHECK_EQUAL (1.0, y1);
120   }
121 
122   cr->set_source_rgb (1.0, 0.5, 0.25);
123   {
124     auto solid =
125       Cairo::RefPtr<Cairo::SolidPattern>::cast_dynamic(cr->get_source ());
126     BOOST_REQUIRE (solid);
127     double rx, gx, bx, ax;
128     solid->get_rgba (rx, gx, bx, ax);
129     BOOST_CHECK_EQUAL (1.0, rx);
130     BOOST_CHECK_EQUAL (0.5, gx);
131     BOOST_CHECK_EQUAL (0.25, bx);
132   }
133   cr->set_source_rgba (0.1, 0.3, 0.5, 0.7);
134   {
135     auto solid =
136       Cairo::RefPtr<Cairo::SolidPattern>::cast_dynamic(cr->get_source ());
137     BOOST_REQUIRE (solid);
138     double rx, gx, bx, ax;
139     solid->get_rgba (rx, gx, bx, ax);
140     BOOST_CHECK_EQUAL (0.1, rx);
141     BOOST_CHECK_EQUAL (0.3, gx);
142     BOOST_CHECK_EQUAL (0.5, bx);
143     BOOST_CHECK_EQUAL (0.7, ax);
144   }
145 }
146 
147 void
test_tolerance()148 test_tolerance ()
149 {
150   CREATE_CONTEXT(cr);
151   cr->set_tolerance (3.0);
152   BOOST_CHECK_EQUAL (3.0, cr->get_tolerance ());
153 }
154 
155 void
test_antialias()156 test_antialias ()
157 {
158   CREATE_CONTEXT(cr);
159   cr->set_antialias (Cairo::ANTIALIAS_GRAY);
160   BOOST_CHECK_EQUAL (Cairo::ANTIALIAS_GRAY, cr->get_antialias ());
161 
162   cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
163   BOOST_CHECK_EQUAL (Cairo::ANTIALIAS_SUBPIXEL, cr->get_antialias ());
164 }
165 
166 void
test_fill_rule()167 test_fill_rule ()
168 {
169   CREATE_CONTEXT(cr);
170   cr->set_fill_rule (Cairo::FILL_RULE_EVEN_ODD);
171   BOOST_CHECK_EQUAL (Cairo::FILL_RULE_EVEN_ODD, cr->get_fill_rule ());
172   cr->set_fill_rule (Cairo::FILL_RULE_WINDING);
173   BOOST_CHECK_EQUAL (Cairo::FILL_RULE_WINDING, cr->get_fill_rule ());
174 }
175 
176 void
test_line_width()177 test_line_width ()
178 {
179   CREATE_CONTEXT(cr);
180   cr->set_line_width (1.0);
181   BOOST_CHECK_EQUAL (1.0, cr->get_line_width ());
182   cr->set_line_width (4.0);
183   BOOST_CHECK_EQUAL (4.0, cr->get_line_width ());
184 }
185 
186 void
test_line_cap()187 test_line_cap ()
188 {
189   CREATE_CONTEXT(cr);
190   cr->set_line_cap (Cairo::LINE_CAP_BUTT);
191   BOOST_CHECK_EQUAL (Cairo::LINE_CAP_BUTT, cr->get_line_cap ());
192   cr->set_line_cap (Cairo::LINE_CAP_ROUND);
193   BOOST_CHECK_EQUAL (Cairo::LINE_CAP_ROUND, cr->get_line_cap ());
194 }
195 
196 void
test_line_join()197 test_line_join ()
198 {
199   CREATE_CONTEXT(cr);
200   cr->set_line_join (Cairo::LINE_JOIN_BEVEL);
201   BOOST_CHECK_EQUAL (Cairo::LINE_JOIN_BEVEL, cr->get_line_join ());
202   cr->set_line_join (Cairo::LINE_JOIN_MITER);
203   BOOST_CHECK_EQUAL (Cairo::LINE_JOIN_MITER, cr->get_line_join ());
204 }
205 
206 void
test_miter_limit()207 test_miter_limit ()
208 {
209   CREATE_CONTEXT (cr);
210   cr->set_miter_limit (1.3);
211   BOOST_CHECK_EQUAL (1.3, cr->get_miter_limit ());
212   cr->set_miter_limit (4.12);
213   BOOST_CHECK_EQUAL (4.12, cr->get_miter_limit ());
214 }
215 
216 void
test_matrix()217 test_matrix ()
218 {
219   // just excercise the functionality
220   CREATE_CONTEXT (cr);
221   Cairo::Matrix matrix;
222   cairo_matrix_init (&matrix, 1.0, 0.1, 0.1, 1.0, 1.5, 1.5);
223   cr->transform(matrix);
224   cairo_matrix_init (&matrix, 1.0, -0.1, -0.1, 1.0, 1.5, 1.5);
225   cr->set_matrix(matrix);
226   cr->set_identity_matrix ();
227   cr->get_matrix (matrix);
228   auto m2 = cr->get_matrix ();
229 }
230 
231 void
test_user_device()232 test_user_device ()
233 {
234   // scale / transform a context, and then verify that user-to-device and
235   // device-to-user things work.
236   CREATE_CONTEXT (cr);
237   cr->scale (2.3, 2.3);
238   double x = 1.8, y = 1.8;
239   cr->user_to_device (x, y);
240   // x = (0.0 + x) * 2.3 => 1.8 * 2.3 = 5.29
241   BOOST_CHECK_EQUAL (4.14, x);
242   BOOST_CHECK_EQUAL (4.14, y);
243   cr->device_to_user (x, y);
244   BOOST_CHECK_EQUAL (1.8, x);
245   BOOST_CHECK_EQUAL (1.8, y);
246   cr->translate (0.5, 0.5);
247   cr->user_to_device (x, y);
248   // x = (0.5 + x) * 2.3 => 2.3 * 2.3 = 5.29
249   BOOST_CHECK_CLOSE (5.29, x, FLT_EPSILON);
250   BOOST_CHECK_CLOSE (5.29, y, FLT_EPSILON);
251 }
252 
253 void
test_draw()254 test_draw ()
255 {
256   CREATE_CONTEXT (cr);
257   // just call a bunch of drawing functions to excercise them a bit.  There's no
258   // rhyme or reason to this, don't expect it to draw anything interesting.
259   cr->begin_new_path ();
260   cr->move_to (1.0, 1.0);
261   cr->line_to (2.0, 2.0);
262   cr->curve_to (0.5, 0.5, 0.5, 0.5, 1.0, 1.0);
263   cr->arc (1.5, 0.5, 0.5, 0, 2 * M_PI);
264   cr->stroke ();
265   cr->arc_negative (1.5, 0.5, 0.5, 0, 2 * M_PI);
266   cr->rel_move_to (0.1, 0.1);
267   cr->rel_line_to (0.5, -0.5);
268   cr->rel_curve_to (0.5, 0.5, 0.5, 0.5, 1.0, 1.0);
269   cr->rectangle (0.0, 0.0, 1.0, 1.0);
270   cr->close_path ();
271   cr->paint ();
272 }
273 
274 void
test_clip()275 test_clip ()
276 {
277   CREATE_CONTEXT (cr);
278   cr->rectangle (0.0, 0.0, 1.0, 1.0);
279   cr->clip ();
280   double x1, y1, x2, y2;
281   cr->get_clip_extents (x1, y1, x2, y2);
282   BOOST_CHECK (x1 == 0.0);
283   BOOST_CHECK (y1 == 0.0);
284   BOOST_CHECK (x2 == 1.0);
285   BOOST_CHECK (y2 == 1.0);
286 }
287 
288 void
test_current_point()289 test_current_point ()
290 {
291   CREATE_CONTEXT (cr);
292   cr->move_to (2.0, 3.0);
293   double x, y;
294   cr->get_current_point (x, y);
295   BOOST_CHECK (x == 2.0);
296   BOOST_CHECK (y == 3.0);
297 }
298 
299 void
test_target()300 test_target ()
301 {
302   auto surf = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, 10, 10); \
303   auto cr = Cairo::Context::create(surf);
304 
305   auto target_surface =
306     Cairo::RefPtr<Cairo::ImageSurface>::cast_dynamic(cr->get_target ());
307   auto bad_surface =
308     Cairo::RefPtr<Cairo::PdfSurface>::cast_dynamic(cr->get_target ());
309   BOOST_CHECK (target_surface);
310   BOOST_CHECK (!bad_surface);
311 
312   // now check for const objects...
313   auto cr2 = Cairo::Context::create(surf);
314 
315   auto target_surface2 =
316     Cairo::RefPtr<const Cairo::ImageSurface>::cast_dynamic(cr2->get_target ());
317   auto bad_surface2 =
318     Cairo::RefPtr<const Cairo::PdfSurface>::cast_dynamic(cr2->get_target ());
319   BOOST_CHECK (target_surface2);
320   BOOST_CHECK (!bad_surface2);
321 }
322 
test_scaled_font()323 void test_scaled_font()
324 {
325   CREATE_CONTEXT (cr);
326   auto face = Cairo::ToyFontFace::create("sans",
327                                                                       Cairo::FONT_SLANT_NORMAL,
328                                                                       Cairo::FONT_WEIGHT_NORMAL);
329   Cairo::Matrix identity;
330   cairo_matrix_init_identity(&identity);
331   auto font = Cairo::ScaledFont::create(face,
332                                                                     identity,
333                                                                     identity,
334                                                                     Cairo::FontOptions());
335   BOOST_CHECK_NO_THROW(cr->set_scaled_font(font));
336   // There's no operator== for ScaledFont, so I'm not sure if there's a way to
337   // compare whether the font we get form get() is the same as the one we set
338   // The following test fails
339   //BOOST_CHECK_EQUAL(font, cr->get_scaled_font());
340 
341   //just put in a pseudo-test for now to excercise the API
342   BOOST_CHECK(cr->get_scaled_font());
343 }
344 
test_font_options()345 void test_font_options()
346 {
347   CREATE_CONTEXT (cr);
348   Cairo::FontOptions options;
349   options.set_antialias(Cairo::ANTIALIAS_GRAY);
350   cr->set_font_options(options);
351   Cairo::FontOptions other;
352   cr->get_font_options(other);
353   BOOST_CHECK(options == other);
354 }
355 
356 test_suite*
init_unit_test_suite(int argc,char * argv[])357 init_unit_test_suite(int argc, char* argv[])
358 {
359   // compile even with -Werror
360   if (argc && argv) {}
361 
362   test_suite* test= BOOST_TEST_SUITE( "Cairo::Context Tests" );
363 
364   test->add (BOOST_TEST_CASE (&test_dashes));
365   test->add (BOOST_TEST_CASE (&test_save_restore));
366   test->add (BOOST_TEST_CASE (&test_operator));
367   test->add (BOOST_TEST_CASE (&test_source));
368   test->add (BOOST_TEST_CASE (&test_tolerance));
369   test->add (BOOST_TEST_CASE (&test_antialias));
370   test->add (BOOST_TEST_CASE (&test_fill_rule));
371   test->add (BOOST_TEST_CASE (&test_line_width));
372   test->add (BOOST_TEST_CASE (&test_line_cap));
373   test->add (BOOST_TEST_CASE (&test_line_join));
374   test->add (BOOST_TEST_CASE (&test_miter_limit));
375   test->add (BOOST_TEST_CASE (&test_matrix));
376   test->add (BOOST_TEST_CASE (&test_user_device));
377   test->add (BOOST_TEST_CASE (&test_draw));
378   test->add (BOOST_TEST_CASE (&test_clip));
379   test->add (BOOST_TEST_CASE (&test_current_point));
380   test->add (BOOST_TEST_CASE (&test_target));
381   test->add (BOOST_TEST_CASE (&test_scaled_font));
382   test->add (BOOST_TEST_CASE (&test_font_options));
383 
384   return test;
385 }
386