/src/demos/demo_cairo.c

http://ftk.googlecode.com/ · C · 405 lines · 321 code · 80 blank · 4 comment · 11 complexity · b1899c90fa3e8fc35d44a142d48c94f3 MD5 · raw file

  1. #include <math.h>
  2. #include "ftk_cairo.h"
  3. static cairo_t* cr = NULL;
  4. static void paint_clip_image(int x, int y, int width, int height)
  5. {
  6. int w, h;
  7. cairo_surface_t *image;
  8. char filename[FTK_MAX_PATH+1] = {0};
  9. cairo_translate (cr, x, y);
  10. cairo_arc (cr, width/2, height/4, width/3, 0, 2*M_PI);
  11. cairo_clip (cr);
  12. cairo_new_path (cr); /* path not consumed by clip()*/
  13. ftk_snprintf(filename, FTK_MAX_PATH, "%s/png3.png",
  14. ftk_config_get_test_data_dir(ftk_default_config()));
  15. ftk_logd("%s:%s\n", __func__, filename);
  16. image = cairo_image_surface_create_from_png (filename);
  17. w = cairo_image_surface_get_width (image);
  18. h = cairo_image_surface_get_height (image);
  19. // cairo_scale (cr, 256.0/w, 256.0/h);
  20. cairo_set_source_surface (cr, image, 0, 0);
  21. cairo_paint (cr);
  22. cairo_surface_destroy (image);
  23. return;
  24. }
  25. static void paint_rect(int x, int y, int width, int height)
  26. {
  27. /* a custom shape that could be wrapped in a function */
  28. double x0 = 25.6, /* parameters like cairo_rectangle */
  29. y0 = 25.6,
  30. rect_width = 204.8,
  31. rect_height = 204.8,
  32. radius = 102.4; /* and an approximate curvature radius */
  33. double x1,y1;
  34. cairo_translate (cr, x, y);
  35. x1=x0+rect_width;
  36. y1=y0+rect_height;
  37. if (!rect_width || !rect_height)
  38. return;
  39. if (rect_width/2<radius) {
  40. if (rect_height/2<radius) {
  41. cairo_move_to (cr, x0, (y0 + y1)/2);
  42. cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
  43. cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
  44. cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
  45. cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
  46. } else {
  47. cairo_move_to (cr, x0, y0 + radius);
  48. cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
  49. cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
  50. cairo_line_to (cr, x1 , y1 - radius);
  51. cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
  52. cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
  53. }
  54. } else {
  55. if (rect_height/2<radius) {
  56. cairo_move_to (cr, x0, (y0 + y1)/2);
  57. cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
  58. cairo_line_to (cr, x1 - radius, y0);
  59. cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
  60. cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
  61. cairo_line_to (cr, x0 + radius, y1);
  62. cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
  63. } else {
  64. cairo_move_to (cr, x0, y0 + radius);
  65. cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
  66. cairo_line_to (cr, x1 - radius, y0);
  67. cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
  68. cairo_line_to (cr, x1 , y1 - radius);
  69. cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
  70. cairo_line_to (cr, x0 + radius, y1);
  71. cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
  72. }
  73. }
  74. cairo_close_path (cr);
  75. cairo_set_source_rgb (cr, 0.5, 0.5, 1);
  76. cairo_fill_preserve (cr);
  77. cairo_set_source_rgba (cr, 0.5, 0, 0, 0.5);
  78. cairo_set_line_width (cr, 10.0);
  79. cairo_stroke (cr);
  80. return;
  81. }
  82. static void paint_pic(int x, int y, int width, int height)
  83. {
  84. int w, h;
  85. cairo_surface_t *image;
  86. cairo_pattern_t *pattern;
  87. cairo_matrix_t matrix;
  88. char filename[FTK_MAX_PATH+1] = {0};
  89. cairo_translate (cr, x, y);
  90. ftk_snprintf(filename, FTK_MAX_PATH, "%s/png3.png",
  91. ftk_config_get_test_data_dir(ftk_default_config()));
  92. image = cairo_image_surface_create_from_png (filename);
  93. w = cairo_image_surface_get_width (image);
  94. h = cairo_image_surface_get_height (image);
  95. pattern = cairo_pattern_create_for_surface (image);
  96. cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
  97. cairo_translate (cr, 128.0, 128.0);
  98. cairo_rotate (cr, M_PI / 4);
  99. cairo_scale (cr, 1 / sqrt (2), 1 / sqrt (2));
  100. cairo_translate (cr, -128.0, -128.0);
  101. cairo_matrix_init_scale (&matrix, w/256.0 * 5.0, h/256.0 * 5.0);
  102. cairo_pattern_set_matrix (pattern, &matrix);
  103. cairo_set_source (cr, pattern);
  104. cairo_rectangle (cr, 0, 0, 256.0, 256.0);
  105. cairo_fill (cr);
  106. cairo_pattern_destroy (pattern);
  107. cairo_surface_destroy (image);
  108. return;
  109. }
  110. static void paint_arrow(int x, int y, int width, int height)
  111. {
  112. cairo_translate (cr, x, y);
  113. cairo_set_line_width (cr, 40.96);
  114. cairo_move_to (cr, 76.8, 84.48);
  115. cairo_rel_line_to (cr, 51.2, -51.2);
  116. cairo_rel_line_to (cr, 51.2, 51.2);
  117. cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER); /* default */
  118. cairo_stroke (cr);
  119. cairo_move_to (cr, 76.8, 161.28);
  120. cairo_rel_line_to (cr, 51.2, -51.2);
  121. cairo_rel_line_to (cr, 51.2, 51.2);
  122. cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL);
  123. cairo_stroke (cr);
  124. cairo_move_to (cr, 76.8, 238.08);
  125. cairo_rel_line_to (cr, 51.2, -51.2);
  126. cairo_rel_line_to (cr, 51.2, 51.2);
  127. cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
  128. cairo_stroke (cr);
  129. return;
  130. }
  131. static void paint_segments(int x, int y, int width, int height)
  132. {
  133. cairo_translate (cr, x, y);
  134. cairo_move_to (cr, 50.0, 75.0);
  135. cairo_line_to (cr, 200.0, 75.0);
  136. cairo_move_to (cr, 50.0, 125.0);
  137. cairo_line_to (cr, 200.0, 125.0);
  138. cairo_move_to (cr, 50.0, 175.0);
  139. cairo_line_to (cr, 200.0, 175.0);
  140. cairo_set_line_width (cr, 30.0);
  141. cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
  142. cairo_stroke (cr);
  143. return;
  144. }
  145. static void paint_ball(int x, int y, int width, int height)
  146. {
  147. cairo_pattern_t *pat;
  148. pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height);
  149. cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 1);
  150. cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1);
  151. cairo_rectangle (cr, x, y, width, height);
  152. cairo_set_source (cr, pat);
  153. cairo_fill (cr);
  154. cairo_pattern_destroy (pat);
  155. pat = cairo_pattern_create_radial (x+115.2, y+102.4, 25.6,
  156. x+102.4, y+102.4, 128.0);
  157. cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1);
  158. cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 1);
  159. cairo_set_source (cr, pat);
  160. cairo_arc (cr, x+width/2, y+height/4, 76.8, 0, 2 * M_PI);
  161. cairo_fill (cr);
  162. cairo_pattern_destroy (pat);
  163. return;
  164. }
  165. static void paint_sin(int x, int y, int width, int height)
  166. {
  167. int i = 0;
  168. int base_y = height/2;
  169. cairo_translate (cr, x, y);
  170. cairo_set_source_rgba (cr, 1.0, 0, 0, 1.0);
  171. cairo_set_line_width (cr, 2);
  172. cairo_move_to (cr, 0, base_y);
  173. cairo_line_to (cr, width, base_y);
  174. cairo_stroke (cr);
  175. cairo_set_line_width (cr, 1);
  176. cairo_move_to (cr, 0, base_y);
  177. cairo_set_source_rgba (cr, 0, 1.0, 0, 1.0);
  178. for(i = 0; i < width; i++)
  179. {
  180. double r = 2 * 3.14 * i /(width >> 2);
  181. int h = height/3 * sin(r);
  182. cairo_line_to (cr, i, base_y + h);
  183. }
  184. ftk_logd("%s:x=%d y=%d base_y=%d width=%d\n", __func__, x, y, base_y, width);
  185. cairo_stroke (cr);
  186. return;
  187. }
  188. static void paint_helloworld(int x, int y, int width, int height)
  189. {
  190. cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
  191. CAIRO_FONT_WEIGHT_BOLD);
  192. cairo_set_font_size (cr, 90.0);
  193. cairo_move_to (cr, x+10.0, y+135.0);
  194. cairo_show_text (cr, "Hello");
  195. cairo_move_to (cr, x+70.0, y+165.0);
  196. cairo_text_path (cr, "void");
  197. cairo_set_source_rgb (cr, 0.5, 0.5, 1);
  198. cairo_fill_preserve (cr);
  199. cairo_set_source_rgb (cr, 0, 0, 0);
  200. cairo_set_line_width (cr, 2.56);
  201. cairo_stroke (cr);
  202. /* draw helping lines */
  203. cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
  204. cairo_arc (cr, x+10.0, y+135.0, 5.12, 0, 2*M_PI);
  205. cairo_close_path (cr);
  206. cairo_arc (cr, x+70.0, y+165.0, 5.12, 0, 2*M_PI);
  207. cairo_fill (cr);
  208. return;
  209. }
  210. static void paint_car(int x, int y, int width, int height)
  211. {
  212. cairo_set_line_width (cr, 6);
  213. cairo_rectangle (cr, x+10, y+10, width-20, 70);
  214. cairo_new_sub_path (cr); cairo_arc (cr, x+64, y+64, 40, 0, 2*M_PI);
  215. cairo_new_sub_path (cr); cairo_arc_negative (cr, width-64, y+64, 40, 0, -2*M_PI);
  216. cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
  217. cairo_set_source_rgb (cr, 0, 0.7, 0); cairo_fill_preserve (cr);
  218. cairo_set_source_rgb (cr, 0, 0, 0); cairo_stroke (cr);
  219. cairo_translate (cr, x, height/2);
  220. cairo_rectangle (cr, 10, 10, width-20, 70);
  221. cairo_new_sub_path (cr); cairo_arc (cr, 64, 64, 40, 0, 2*M_PI);
  222. cairo_new_sub_path (cr); cairo_arc_negative (cr, width-64, 64, 40, 0, -2*M_PI);
  223. cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
  224. cairo_set_source_rgb (cr, 0, 0, 0.9); cairo_fill_preserve (cr);
  225. cairo_set_source_rgb (cr, 0, 0, 0); cairo_stroke (cr);
  226. return;
  227. }
  228. typedef void (*PaintFunc)(int x, int y, int width, int height);
  229. static size_t g_index = 0;
  230. static const PaintFunc paints[] =
  231. {
  232. paint_car,
  233. paint_sin,
  234. // paint_helloworld,
  235. paint_ball,
  236. paint_segments,
  237. paint_arrow,
  238. paint_pic,
  239. paint_rect,
  240. paint_clip_image
  241. };
  242. static Ret on_paint(void* ctx, void* obj)
  243. {
  244. FtkWidget* thiz = obj;
  245. FTK_BEGIN_PAINT(x, y, width, height, canvas);
  246. ftk_logd("%s:%d\n", __func__, __LINE__);
  247. if(cr == NULL)
  248. {
  249. cairo_surface_t* surface = ftk_cairo_surface_create(thiz);
  250. cr = cairo_create(surface);
  251. cairo_surface_destroy(surface);
  252. ftk_logd("%s:%d\n", __func__, __LINE__);
  253. }
  254. cairo_save (cr);
  255. cairo_reset_clip (cr);
  256. cairo_identity_matrix (cr);
  257. cairo_new_path (cr);
  258. cairo_rectangle(cr, x, y, width, height);
  259. cairo_clip (cr);
  260. ftk_logd("%s:%d index=%d\n", __func__, __LINE__, g_index);
  261. paints[g_index](x, y, width, height);
  262. ftk_logd("%s:%d\n", __func__, __LINE__);
  263. cairo_restore (cr);
  264. FTK_END_PAINT();
  265. ftk_logd("%s:%d\n", __func__, __LINE__);
  266. return RET_OK;
  267. }
  268. static Ret button_prev_clicked(void* ctx, void* obj)
  269. {
  270. g_index = g_index > 0 ? g_index - 1 : 0;
  271. ftk_widget_invalidate(ftk_widget_lookup(ctx, 100));
  272. return RET_OK;
  273. }
  274. static Ret button_next_clicked(void* ctx, void* obj)
  275. {
  276. g_index++;
  277. g_index = g_index % (sizeof(paints)/sizeof(paints[0]));
  278. ftk_widget_invalidate(ftk_widget_lookup(ctx, 100));
  279. return RET_OK;
  280. }
  281. static Ret button_quit_clicked(void* ctx, void* obj)
  282. {
  283. ftk_widget_unref(ctx);
  284. return RET_OK;
  285. }
  286. #ifdef FTK_AS_PLUGIN
  287. #include "ftk_app_demo.h"
  288. FTK_HIDE int FTK_MAIN(int argc, char* argv[]);
  289. FtkApp* ftk_app_demo_cairo_create()
  290. {
  291. return ftk_app_demo_create(_("cairo"), ftk_main);
  292. }
  293. #else
  294. #define FTK_HIDE extern
  295. #endif /*FTK_AS_PLUGIN*/
  296. FTK_HIDE int FTK_MAIN(int argc, char* argv[])
  297. {
  298. int width = 0;
  299. int height = 0;
  300. FtkWidget* win = NULL;
  301. FtkWidget* button = NULL;
  302. FtkWidget* painter = NULL;
  303. FTK_INIT(argc, argv);
  304. win = ftk_app_window_create();
  305. ftk_window_set_animation_hint(win, "app_main_window");
  306. width = ftk_widget_width(win);
  307. height = ftk_widget_height(win);
  308. button = ftk_button_create(win, 0, 10, width/3, 60);
  309. ftk_widget_set_text(button, "prev");
  310. ftk_button_set_clicked_listener(button, button_prev_clicked, win);
  311. button = ftk_button_create(win, width/3, 10, width/3, 60);
  312. ftk_widget_set_text(button, "next");
  313. ftk_button_set_clicked_listener(button, button_next_clicked, win);
  314. button = ftk_button_create(win, width*2/3, 10, width/3, 60);
  315. ftk_widget_set_text(button, "quit");
  316. ftk_button_set_clicked_listener(button, button_quit_clicked, win);
  317. painter = ftk_painter_create(win, 0, 70, width, height-80);
  318. ftk_widget_set_id(painter, 100);
  319. ftk_painter_set_paint_listener(painter, on_paint, NULL);
  320. ftk_widget_set_text(win, "cairo demo");
  321. ftk_widget_show_all(win, 1);
  322. FTK_QUIT_WHEN_WIDGET_CLOSE(win);
  323. FTK_RUN();
  324. return 0;
  325. }