record90.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. /*
  2. * Copyright © 2005 Red Hat, Inc.
  3. * Copyright © 2011 Intel Corporation
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software
  6. * and its documentation for any purpose is hereby granted without
  7. * fee, provided that the above copyright notice appear in all copies
  8. * and that both that copyright notice and this permission notice
  9. * appear in supporting documentation, and that the name of
  10. * Red Hat, Inc. not be used in advertising or publicity pertaining to
  11. * distribution of the software without specific, written prior
  12. * permission. Red Hat, Inc. makes no representations about the
  13. * suitability of this software for any purpose. It is provided "as
  14. * is" without express or implied warranty.
  15. *
  16. * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  17. * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  18. * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
  19. * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  20. * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  21. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  22. * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23. *
  24. * Authors:
  25. * Carl D. Worth <cworth@cworth.org>
  26. * Chris Wilson <chris@chris-wilson.co.uk>
  27. */
  28. #include "cairo-test.h"
  29. #define TEXT_SIZE 12
  30. #define SIZE 60 /* needs to be big to check large area effects (dithering) */
  31. #define PAD 2
  32. #define TT_SIZE 100
  33. #define TT_PAD 5
  34. #define TT_FONT_SIZE 32.0
  35. #define GENERATE_REF 0
  36. static uint32_t data[16] = {
  37. 0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
  38. 0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
  39. 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff,
  40. 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff
  41. };
  42. static const char *png_filename = "romedalen.png";
  43. static cairo_t *
  44. paint (cairo_t *cr)
  45. {
  46. cairo_set_source_rgb (cr, 0, 0, 1);
  47. cairo_paint (cr);
  48. cairo_translate (cr, 2, 2);
  49. cairo_scale (cr, 0.5, 0.5);
  50. cairo_set_source_rgb (cr, 1, 0, 0);
  51. cairo_paint (cr);
  52. return cr;
  53. }
  54. static cairo_t *
  55. paint_alpha (cairo_t *cr)
  56. {
  57. cairo_surface_t *surface;
  58. surface = cairo_image_surface_create_for_data ((unsigned char *) data,
  59. CAIRO_FORMAT_RGB24, 4, 4, 16);
  60. cairo_test_paint_checkered (cr);
  61. cairo_scale (cr, 4, 4);
  62. cairo_set_source_surface (cr, surface, 2 , 2);
  63. cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
  64. cairo_paint_with_alpha (cr, 0.5);
  65. cairo_surface_finish (surface); /* data will go out of scope */
  66. cairo_surface_destroy (surface);
  67. return cr;
  68. }
  69. static cairo_t *
  70. paint_alpha_solid_clip (cairo_t *cr)
  71. {
  72. cairo_test_paint_checkered (cr);
  73. cairo_rectangle (cr, 2.5, 2.5, 27, 27);
  74. cairo_clip (cr);
  75. cairo_set_source_rgb (cr, 1., 0.,0.);
  76. cairo_paint_with_alpha (cr, 0.5);
  77. return cr;
  78. }
  79. static cairo_t *
  80. paint_alpha_clip (cairo_t *cr)
  81. {
  82. cairo_surface_t *surface;
  83. surface = cairo_image_surface_create_for_data ((unsigned char *) data,
  84. CAIRO_FORMAT_RGB24, 4, 4, 16);
  85. cairo_test_paint_checkered (cr);
  86. cairo_rectangle (cr, 10.5, 10.5, 11, 11);
  87. cairo_clip (cr);
  88. cairo_scale (cr, 4, 4);
  89. cairo_set_source_surface (cr, surface, 2 , 2);
  90. cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
  91. cairo_paint_with_alpha (cr, 0.5);
  92. cairo_surface_finish (surface); /* data will go out of scope */
  93. cairo_surface_destroy (surface);
  94. return cr;
  95. }
  96. static cairo_t *
  97. paint_alpha_clip_mask (cairo_t *cr)
  98. {
  99. cairo_surface_t *surface;
  100. surface = cairo_image_surface_create_for_data ((unsigned char *) data,
  101. CAIRO_FORMAT_RGB24, 4, 4, 16);
  102. cairo_test_paint_checkered (cr);
  103. cairo_move_to (cr, 16, 5);
  104. cairo_line_to (cr, 5, 16);
  105. cairo_line_to (cr, 16, 27);
  106. cairo_line_to (cr, 27, 16);
  107. cairo_clip (cr);
  108. cairo_scale (cr, 4, 4);
  109. cairo_set_source_surface (cr, surface, 2 , 2);
  110. cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
  111. cairo_paint_with_alpha (cr, 0.5);
  112. cairo_surface_finish (surface); /* data will go out of scope */
  113. cairo_surface_destroy (surface);
  114. return cr;
  115. }
  116. static cairo_t *
  117. select_font_face (cairo_t *cr)
  118. {
  119. /* We draw in the default black, so paint white first. */
  120. cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
  121. cairo_paint (cr);
  122. cairo_set_source_rgb (cr, 0, 0, 0); /* black */
  123. cairo_set_font_size (cr, TEXT_SIZE);
  124. cairo_move_to (cr, 0, TEXT_SIZE);
  125. cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Serif",
  126. CAIRO_FONT_SLANT_NORMAL,
  127. CAIRO_FONT_WEIGHT_NORMAL);
  128. cairo_show_text (cr, "i-am-serif");
  129. cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
  130. CAIRO_FONT_SLANT_NORMAL,
  131. CAIRO_FONT_WEIGHT_NORMAL);
  132. cairo_show_text (cr, " i-am-sans");
  133. cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans Mono",
  134. CAIRO_FONT_SLANT_NORMAL,
  135. CAIRO_FONT_WEIGHT_NORMAL);
  136. cairo_show_text (cr, " i-am-mono");
  137. return cr;
  138. }
  139. static cairo_t *
  140. fill_alpha (cairo_t *cr)
  141. {
  142. const double alpha = 1./3;
  143. int n;
  144. /* flatten to white */
  145. cairo_set_source_rgb (cr, 1, 1, 1);
  146. cairo_paint (cr);
  147. /* square */
  148. cairo_rectangle (cr, PAD, PAD, SIZE, SIZE);
  149. cairo_set_source_rgba (cr, 1, 0, 0, alpha);
  150. cairo_fill (cr);
  151. /* circle */
  152. cairo_translate (cr, SIZE + 2 * PAD, 0);
  153. cairo_arc (cr, PAD + SIZE / 2., PAD + SIZE / 2., SIZE / 2., 0, 2 * M_PI);
  154. cairo_set_source_rgba (cr, 0, 1, 0, alpha);
  155. cairo_fill (cr);
  156. /* triangle */
  157. cairo_translate (cr, 0, SIZE + 2 * PAD);
  158. cairo_move_to (cr, PAD + SIZE / 2, PAD);
  159. cairo_line_to (cr, PAD + SIZE, PAD + SIZE);
  160. cairo_line_to (cr, PAD, PAD + SIZE);
  161. cairo_set_source_rgba (cr, 0, 0, 1, alpha);
  162. cairo_fill (cr);
  163. /* star */
  164. cairo_translate (cr, -(SIZE + 2 * PAD) + SIZE/2., SIZE/2.);
  165. for (n = 0; n < 5; n++) {
  166. cairo_line_to (cr,
  167. SIZE/2 * cos (2*n * 2*M_PI / 10),
  168. SIZE/2 * sin (2*n * 2*M_PI / 10));
  169. cairo_line_to (cr,
  170. SIZE/4 * cos ((2*n+1)*2*M_PI / 10),
  171. SIZE/4 * sin ((2*n+1)*2*M_PI / 10));
  172. }
  173. cairo_set_source_rgba (cr, 0, 0, 0, alpha);
  174. cairo_fill (cr);
  175. return cr;
  176. }
  177. static cairo_t *
  178. self_intersecting (cairo_t *cr)
  179. {
  180. cairo_set_source_rgb (cr, 1, 1, 1);
  181. cairo_paint (cr);
  182. cairo_translate (cr, 1.0, 1.0);
  183. cairo_set_source_rgb (cr, 1, 0, 0); /* red */
  184. /* First draw the desired shape with a fill */
  185. cairo_rectangle (cr, 0.5, 0.5, 4.0, 4.0);
  186. cairo_rectangle (cr, 3.5, 3.5, 4.0, 4.0);
  187. cairo_rectangle (cr, 3.5, 1.5, -2.0, 2.0);
  188. cairo_rectangle (cr, 6.5, 4.5, -2.0, 2.0);
  189. cairo_fill (cr);
  190. /* Then try the same thing with a stroke */
  191. cairo_translate (cr, 0, 10);
  192. cairo_move_to (cr, 1.0, 1.0);
  193. cairo_rel_line_to (cr, 3.0, 0.0);
  194. cairo_rel_line_to (cr, 0.0, 6.0);
  195. cairo_rel_line_to (cr, 3.0, 0.0);
  196. cairo_rel_line_to (cr, 0.0, -3.0);
  197. cairo_rel_line_to (cr, -6.0, 0.0);
  198. cairo_close_path (cr);
  199. cairo_set_line_width (cr, 1.0);
  200. cairo_stroke (cr);
  201. return cr;
  202. }
  203. static void
  204. draw_text_transform (cairo_t *cr)
  205. {
  206. cairo_matrix_t tm;
  207. /* skew */
  208. cairo_matrix_init (&tm, 1, 0,
  209. -0.25, 1,
  210. 0, 0);
  211. cairo_matrix_scale (&tm, TT_FONT_SIZE, TT_FONT_SIZE);
  212. cairo_set_font_matrix (cr, &tm);
  213. cairo_new_path (cr);
  214. cairo_move_to (cr, 50, TT_SIZE-TT_PAD);
  215. cairo_show_text (cr, "A");
  216. /* rotate and scale */
  217. cairo_matrix_init_rotate (&tm, M_PI / 2);
  218. cairo_matrix_scale (&tm, TT_FONT_SIZE, TT_FONT_SIZE * 2.0);
  219. cairo_set_font_matrix (cr, &tm);
  220. cairo_new_path (cr);
  221. cairo_move_to (cr, TT_PAD, TT_PAD + 25);
  222. cairo_show_text (cr, "A");
  223. cairo_matrix_init_rotate (&tm, M_PI / 2);
  224. cairo_matrix_scale (&tm, TT_FONT_SIZE * 2.0, TT_FONT_SIZE);
  225. cairo_set_font_matrix (cr, &tm);
  226. cairo_new_path (cr);
  227. cairo_move_to (cr, TT_PAD, TT_PAD + 50);
  228. cairo_show_text (cr, "A");
  229. }
  230. static cairo_t *
  231. text_transform (cairo_t *cr)
  232. {
  233. const cairo_test_context_t *ctx = cairo_test_get_context (cr);
  234. cairo_pattern_t *pattern;
  235. cairo_set_source_rgb (cr, 1., 1., 1.);
  236. cairo_paint (cr);
  237. cairo_set_source_rgb (cr, 0., 0., 0.);
  238. cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
  239. CAIRO_FONT_SLANT_NORMAL,
  240. CAIRO_FONT_WEIGHT_NORMAL);
  241. draw_text_transform (cr);
  242. cairo_translate (cr, TT_SIZE, TT_SIZE);
  243. cairo_rotate (cr, M_PI);
  244. pattern = cairo_test_create_pattern_from_png (ctx, png_filename);
  245. cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
  246. cairo_set_source (cr, pattern);
  247. cairo_pattern_destroy (pattern);
  248. draw_text_transform (cr);
  249. return cr;
  250. }
  251. /* And here begins the recording and replaying... */
  252. static cairo_t *
  253. record_create (cairo_t *target)
  254. {
  255. cairo_surface_t *surface;
  256. cairo_t *cr;
  257. surface = cairo_recording_surface_create (cairo_surface_get_content (cairo_get_target (target)), NULL);
  258. cr = cairo_create (surface);
  259. cairo_surface_destroy (surface);
  260. return cr;
  261. }
  262. static cairo_surface_t *
  263. record_get (cairo_t *target)
  264. {
  265. cairo_surface_t *surface;
  266. surface = cairo_surface_reference (cairo_get_target (target));
  267. cairo_destroy (target);
  268. return surface;
  269. }
  270. static cairo_test_status_t
  271. record_replay (cairo_t *cr, cairo_t *(*func)(cairo_t *), int width, int height)
  272. {
  273. cairo_surface_t *surface;
  274. int x, y;
  275. #if GENERATE_REF
  276. cairo_translate(cr, width, 0);
  277. cairo_rotate (cr, M_PI/2);
  278. func(cr);
  279. #else
  280. surface = record_get (func (record_create (cr)));
  281. cairo_translate(cr, width, 0);
  282. cairo_rotate (cr, M_PI/2);
  283. cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
  284. cairo_set_source_surface (cr, surface, 0, 0);
  285. cairo_surface_destroy (surface);
  286. cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
  287. for (y = 0; y < width; y += 2) {
  288. for (x = 0; x < height; x += 2) {
  289. cairo_rectangle (cr, x, y, 2, 2);
  290. cairo_clip (cr);
  291. cairo_paint (cr);
  292. cairo_reset_clip (cr);
  293. }
  294. }
  295. #endif
  296. return CAIRO_TEST_SUCCESS;
  297. }
  298. static cairo_test_status_t
  299. record_paint (cairo_t *cr, int width, int height)
  300. {
  301. return record_replay (cr, paint, width, height);
  302. }
  303. static cairo_test_status_t
  304. record_paint_alpha (cairo_t *cr, int width, int height)
  305. {
  306. return record_replay (cr, paint_alpha, width, height);
  307. }
  308. static cairo_test_status_t
  309. record_paint_alpha_solid_clip (cairo_t *cr, int width, int height)
  310. {
  311. return record_replay (cr, paint_alpha_solid_clip, width, height);
  312. }
  313. static cairo_test_status_t
  314. record_paint_alpha_clip (cairo_t *cr, int width, int height)
  315. {
  316. return record_replay (cr, paint_alpha_clip, width, height);
  317. }
  318. static cairo_test_status_t
  319. record_paint_alpha_clip_mask (cairo_t *cr, int width, int height)
  320. {
  321. return record_replay (cr, paint_alpha_clip_mask, width, height);
  322. }
  323. static cairo_test_status_t
  324. record_fill_alpha (cairo_t *cr, int width, int height)
  325. {
  326. return record_replay (cr, fill_alpha, width, height);
  327. }
  328. static cairo_test_status_t
  329. record_self_intersecting (cairo_t *cr, int width, int height)
  330. {
  331. return record_replay (cr, self_intersecting, width, height);
  332. }
  333. static cairo_test_status_t
  334. record_select_font_face (cairo_t *cr, int width, int height)
  335. {
  336. return record_replay (cr, select_font_face, width, height);
  337. }
  338. static cairo_test_status_t
  339. record_text_transform (cairo_t *cr, int width, int height)
  340. {
  341. return record_replay (cr, text_transform, width, height);
  342. }
  343. CAIRO_TEST (record90_paint,
  344. "Test replayed calls to cairo_paint",
  345. "paint,record", /* keywords */
  346. NULL, /* requirements */
  347. 8, 8,
  348. NULL, record_paint)
  349. CAIRO_TEST (record90_paint_alpha,
  350. "Simple test of cairo_paint_with_alpha",
  351. "record, paint, alpha", /* keywords */
  352. NULL, /* requirements */
  353. 2, 32,
  354. NULL, record_paint_alpha)
  355. CAIRO_TEST (record90_paint_alpha_solid_clip,
  356. "Simple test of cairo_paint_with_alpha+unaligned clip",
  357. "record, paint, alpha, clip", /* keywords */
  358. NULL, /* requirements */
  359. 32, 32,
  360. NULL, record_paint_alpha_solid_clip)
  361. CAIRO_TEST (record90_paint_alpha_clip,
  362. "Simple test of cairo_paint_with_alpha+unaligned clip",
  363. "record, paint, alpha, clip", /* keywords */
  364. NULL, /* requirements */
  365. 32, 32,
  366. NULL, record_paint_alpha_clip)
  367. CAIRO_TEST (record90_paint_alpha_clip_mask,
  368. "Simple test of cairo_paint_with_alpha+triangular clip",
  369. "record, paint, alpha, clip", /* keywords */
  370. NULL, /* requirements */
  371. 32, 32,
  372. NULL, record_paint_alpha_clip_mask)
  373. CAIRO_TEST (record90_fill_alpha,
  374. "Tests using set_rgba();fill()",
  375. "record,fill, alpha", /* keywords */
  376. NULL, /* requirements */
  377. 2*SIZE + 4*PAD, 2*SIZE + 4*PAD,
  378. NULL, record_fill_alpha)
  379. CAIRO_TEST (record90_select_font_face,
  380. "Tests using cairo_select_font_face to draw text in different faces",
  381. "record, font", /* keywords */
  382. NULL, /* requirements */
  383. TEXT_SIZE + 4, 192,
  384. NULL, record_select_font_face)
  385. CAIRO_TEST (record90_self_intersecting,
  386. "Test strokes of self-intersecting paths",
  387. "record, stroke, trap", /* keywords */
  388. NULL, /* requirements */
  389. 20, 10,
  390. NULL, record_self_intersecting)
  391. CAIRO_TEST (record90_text_transform,
  392. "Test various applications of the font matrix",
  393. "record, text, transform", /* keywords */
  394. NULL, /* requirements */
  395. TT_SIZE, TT_SIZE,
  396. NULL, record_text_transform)