You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

963 lines
22KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2012 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU Library General Public License as published */
  6. /* by the Free Software Foundation; either version 2 of the License, or (at */
  7. /* your option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. /* This class emulates the FLTK graphics drawing API using the Cairo
  19. * library. The advantage of doing this is that it provides
  20. * antialiasing and transparency on X11 for all FLTK widgets.
  21. *
  22. * The implementation inherits from the Xlib driver and attempts to
  23. * keep colors, clipping, and matrix transformations in sync, so that
  24. * calls to the base Xlib and Cairo routines can be mixed with the
  25. * expected results.
  26. *
  27. * Fonts are still rendered using XFT. And since the FLTK image
  28. * drawing implementation already uses XRender, there would seem to be
  29. * little advantage to using Cairo for that either.
  30. *
  31. * Alpha values can be encoded into Fl_Color values by using the new
  32. * fl_color_add_alpha function--with the caveat that 100% transparency
  33. * (an Alpha of 0) is unsupported. This allows existing boxes and
  34. * widgets to be drawn with transparency simply by setting their
  35. * color() to one with an alpha value encoded.
  36. *
  37. * Antialiasing can be turned on and off with the new
  38. * fl_set_antialias() function. However, it should be noted that, even
  39. * with antialiasing disabled drawing complex lines and polygons is
  40. * still significantly slower with Cairo than with the base FLTK
  41. * routines.
  42. *
  43. */
  44. #include <config.h>
  45. #include <FL/Fl.H>
  46. double fl_hxo = 0.0;
  47. double fl_hyo = 0.5;
  48. double fl_vxo = 0.5;
  49. double fl_vyo = 0.0;
  50. double fl_vho = 1.0;
  51. double fl_hwo = 1.0;
  52. #define HXO(n) ( n + fl_hxo )
  53. #define HYO(n) ( n + fl_hyo )
  54. #define VXO(n) ( n + fl_vxo )
  55. #define VYO(n) ( n + fl_vyo )
  56. #define VHO(n) ( n + fl_vho )
  57. #define HWO(n) ( n + fl_hwo )
  58. Fl_Color fl_color_add_alpha ( Fl_Color c, uchar alpha )
  59. {
  60. if ( !( c & 0xFFFFFF00 ) )
  61. {
  62. /* this is an indexed color or black */
  63. if ( c & 0x000000FF )
  64. {
  65. /* this is an indexed color */
  66. uchar r,g,b;
  67. Fl::get_color( c, r, g, b );
  68. c = fl_rgb_color( r, g, b );
  69. }
  70. else
  71. {
  72. /* this is black */
  73. if ( 0 == alpha )
  74. {
  75. /* sorry, you can't have zero opacity because we don't
  76. * have enough bits and it doesn't make much sense anyway */
  77. alpha = 255;
  78. }
  79. /* hack to represent black */
  80. c = 0x01010100;
  81. }
  82. }
  83. return ( c & 0xFFFFFF00 ) | alpha;
  84. }
  85. #include <FL/x.H>
  86. #include <cairo/cairo.h>
  87. #include <FL/Fl_Cairo.H>
  88. #include <FL/fl_draw.H>
  89. #include <math.h>
  90. #include <FL/Fl_Device.H>
  91. static double lw = 1;
  92. static double hlw;
  93. static cairo_antialias_t aa = CAIRO_ANTIALIAS_GRAY;
  94. static int npoints = 0;
  95. cairo_matrix_t Fl_Cairo_Graphics_Driver::m;
  96. cairo_matrix_t Fl_Cairo_Graphics_Driver::stack[FL_MATRIX_STACK_SIZE];
  97. int Fl_Cairo_Graphics_Driver::sptr;
  98. #define cairo_set_antialias( cr, aa )
  99. Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver ( ) : Fl_Xlib_Graphics_Driver ()
  100. {
  101. // rstackptr = 0;
  102. }
  103. /* void Fl_Cairo_Graphics_Driver::set_current ( void ) */
  104. /* { */
  105. /* Window root; */
  106. /* int x, y; */
  107. /* unsigned int w, h, bw, d; */
  108. /* XGetGeometry( fl_display, fl_window, &root, &x, &y, &w, &h, &bw, &d ); */
  109. /* fl_cairo_surface = cairo_create_surface( fl_gc, w, h ); */
  110. /* /\* FIXME: how are we going to free this? *\/ */
  111. /* fl_cairo_context = cairo_create( fl_cairo_surface ); */
  112. /* cairo_surface_destroy( fl_cairo_surface ); */
  113. /* fl_cairo_surface = 0; */
  114. /* } */
  115. #define set_cairo_matrix() \
  116. { \
  117. cairo_t *cr = fl_cairo_context; \
  118. if ( sptr ) \
  119. cairo_set_matrix( cr, &m ); \
  120. else \
  121. cairo_identity_matrix( cr ); \
  122. }
  123. #define restore_cairo_matrix() \
  124. { \
  125. cairo_t *cr = fl_cairo_context; \
  126. cairo_identity_matrix( cr ); \
  127. }
  128. void Fl_Cairo_Graphics_Driver::push_matrix ( void )
  129. {
  130. cairo_t *cr = Fl::cairo_cc();
  131. cairo_get_matrix( cr, &m );
  132. if (sptr==FL_MATRIX_STACK_SIZE)
  133. Fl::error("fl_push_matrix(): matrix stack overflow.");
  134. else
  135. stack[sptr++] = m;
  136. }
  137. void Fl_Cairo_Graphics_Driver::pop_matrix ( void )
  138. {
  139. cairo_t *cr = Fl::cairo_cc();
  140. if (sptr==0)
  141. Fl::error("fl_pop_matrix(): matrix stack underflow.");
  142. else
  143. m = stack[--sptr];
  144. set_cairo_matrix();
  145. }
  146. void Fl_Cairo_Graphics_Driver::translate ( double x, double y )
  147. {
  148. cairo_t *cr = Fl::cairo_cc();
  149. cairo_matrix_translate( &m, x, y );
  150. set_cairo_matrix();
  151. }
  152. void Fl_Cairo_Graphics_Driver::scale ( double x, double y )
  153. {
  154. cairo_t *cr = Fl::cairo_cc();
  155. cairo_matrix_scale( &m, x, y );
  156. set_cairo_matrix();
  157. }
  158. void Fl_Cairo_Graphics_Driver::rotate ( double a )
  159. {
  160. cairo_t *cr = Fl::cairo_cc();
  161. cairo_matrix_rotate( &m, a * ( M_PI / 180.0 ) );
  162. set_cairo_matrix();
  163. }
  164. void Fl_Cairo_Graphics_Driver::mult_matrix ( double a, double b, double c, double d, double x, double y )
  165. {
  166. cairo_t *cr = Fl::cairo_cc();
  167. cairo_matrix_t m2;
  168. cairo_matrix_init( &m2, a, b, c, d, x, y );
  169. cairo_matrix_multiply( &m, &m2, &m );
  170. set_cairo_matrix();
  171. }
  172. void Fl_Cairo_Graphics_Driver::line_style ( int style, int t, char* )
  173. {
  174. cairo_t *cr = Fl::cairo_cc();
  175. if ( t == 0 || t == 1 )
  176. {
  177. double w1, w2;
  178. w1 = w2 = 1.0;
  179. cairo_device_to_user_distance (cr, &w1, &w2);
  180. lw = w1 > w2 ? w1 : w2;
  181. }
  182. else
  183. lw = t;
  184. hlw = lw / 2.0;
  185. cairo_set_line_width( cr, lw );
  186. cairo_set_line_cap( cr, CAIRO_LINE_CAP_BUTT );
  187. if ( style & FL_DASH )
  188. {
  189. const double dash[] = { lw, lw };
  190. int len = sizeof(dash) / sizeof(dash[0]);
  191. cairo_set_dash( cr, dash, len, 0 );
  192. }
  193. else if ( style & FL_DOT )
  194. {
  195. const double dash[] = { lw, lw };
  196. int len = sizeof(dash) / sizeof(dash[0]);
  197. cairo_set_dash( cr, dash, len, 0 );
  198. cairo_set_line_cap( cr, CAIRO_LINE_CAP_ROUND );
  199. }
  200. else
  201. {
  202. cairo_set_dash( cr, NULL, 0, 0 );
  203. }
  204. }
  205. void Fl_Cairo_Graphics_Driver::color ( Fl_Color c )
  206. {
  207. uchar r,g,b;
  208. Fl_Xlib_Graphics_Driver::color( c );
  209. if ( ( c & 0x000000ff ) && ! ( c & 0xFFFFFF00 ) )
  210. {
  211. /* color is indexed, get the RGB value */
  212. Fl::get_color( c, r, g, b );
  213. /* FIXME: temp! */
  214. color( r, g, b );
  215. /* color( 255, 0, 0, 50 ); */
  216. }
  217. else
  218. {
  219. Fl::get_color( c & 0xFFFFFF00, r, g, b );
  220. /* lower 8 bits become alpha. */
  221. uchar a = c & 0x000000ff;
  222. if ( ! a )
  223. a = 255;
  224. /* /\* HACK to represent black *\/ */
  225. /* if ( ( c & 0xFFFFFF00 ) == 0x01010100 ) */
  226. /* r = g = b = 0; */
  227. color( r, g, b, a );
  228. }
  229. }
  230. void Fl_Cairo_Graphics_Driver::color ( uchar r, uchar g, uchar b )
  231. {
  232. cairo_t *cr = Fl::cairo_cc();
  233. Fl_Xlib_Graphics_Driver::color( r, g, b );
  234. if ( ! cr )
  235. return;
  236. cairo_set_source_rgb( cr, r / 255.0f, g / 255.0f, b / 255.0f );
  237. }
  238. void fl_set_antialias ( int v )
  239. {
  240. cairo_t *cr = Fl::cairo_cc();
  241. switch ( v )
  242. {
  243. case FL_ANTIALIAS_DEFAULT:
  244. cairo_set_antialias( cr, aa = CAIRO_ANTIALIAS_DEFAULT );
  245. break;
  246. case FL_ANTIALIAS_ON:
  247. cairo_set_antialias( cr, aa = CAIRO_ANTIALIAS_GRAY );
  248. break;
  249. case FL_ANTIALIAS_OFF:
  250. cairo_set_antialias( cr, aa = CAIRO_ANTIALIAS_NONE );
  251. break;
  252. }
  253. }
  254. void Fl_Cairo_Graphics_Driver::color ( Fl_Color c, uchar a )
  255. {
  256. uchar r,g,b;
  257. Fl::get_color( c, r, g, b );
  258. Fl_Xlib_Graphics_Driver::color( c );
  259. color( r, g, b, a);
  260. }
  261. void Fl_Cairo_Graphics_Driver::color (uchar r, uchar g, uchar b, uchar a )
  262. {
  263. cairo_t *cr = Fl::cairo_cc();
  264. // Fl_Xlib_Graphics_Driver::color( r, g, b );
  265. if ( ! cr )
  266. return;
  267. cairo_set_source_rgba( cr, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f );
  268. }
  269. void Fl_Cairo_Graphics_Driver::circle( double x, double y, double r )
  270. {
  271. cairo_t *cr = Fl::cairo_cc();
  272. cairo_arc( cr, x, y, r, 0, 2.0f * M_PI );
  273. restore_cairo_matrix();
  274. if ( what == POLYGON )
  275. cairo_fill( cr );
  276. else
  277. cairo_stroke( cr );
  278. set_cairo_matrix();
  279. }
  280. /* static void add_arc( int x, int y, int w, int h, double a1, double a2 ) */
  281. /* { */
  282. /* cairo_t *cr = Fl::cairo_cc(); */
  283. /* /\* const double line_width = cairo_get_line_width( cr ); *\/ */
  284. /* const double cx = x + ( 0.5f * w ); */
  285. /* const double cy = y + ( 0.5f * h ); */
  286. /* /\* cairo_save( cr ); *\/ */
  287. /* /\* cairo_translate( cr, cx, cy ); *\/ */
  288. /* /\* cairo_scale( cr, w, h ); *\/ */
  289. /* /\* if ( a1 > a2 ) *\/ */
  290. /* /\* cairo_arc( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); *\/ */
  291. /* /\* else *\/ */
  292. /* /\* cairo_arc_negative( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); *\/ */
  293. /* cairo_save( cr ); */
  294. /* cairo_translate( cr, cx, cy ); */
  295. /* cairo_scale( cr, w - 1, h - 1 ); */
  296. /* if ( a1 > a2 ) */
  297. /* cairo_arc( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); */
  298. /* else */
  299. /* cairo_arc_negative( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); */
  300. /* cairo_restore( cr ); */
  301. /* } */
  302. static void add_arc( int x, int y, int w, int h, double a1, double a2, bool pie )
  303. {
  304. cairo_t *cr = Fl::cairo_cc();
  305. double a1R = a1 * ( M_PI / 180.0 );
  306. double a2R = a2 * ( M_PI / 180.0 );
  307. double cx = x + 0.5 * w, cy = y + 0.5 * h;
  308. cairo_save( cr );
  309. cairo_translate( cr, cx, cy );
  310. // cairo_scale( cr, (w - lw), 0 - ((h - lw) ));
  311. cairo_scale( cr, w, 0 - h );
  312. if ( a1 > a2 )
  313. cairo_arc_negative( cr, 0.0, 0.0, 0.5, a1R, a2R );
  314. else
  315. cairo_arc( cr, 0.0, 0.0, 0.5, a1R, a2R );
  316. if ( pie )
  317. {
  318. cairo_line_to( cr, 0, 0 );
  319. cairo_close_path( cr );
  320. }
  321. cairo_restore( cr );
  322. }
  323. void Fl_Cairo_Graphics_Driver::arc( int x, int y, int w, int h, double a1, double a2 )
  324. {
  325. cairo_t *cr = Fl::cairo_cc();
  326. add_arc( x, y, w, h, a1, a2, false );
  327. restore_cairo_matrix();
  328. cairo_stroke( cr );
  329. set_cairo_matrix();
  330. }
  331. void Fl_Cairo_Graphics_Driver::arc( double x, double y, double r, double a1, double a2 )
  332. {
  333. cairo_t *cr = Fl::cairo_cc();
  334. cairo_close_path( cr );
  335. cairo_arc( cr, x, y, r, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 ));
  336. }
  337. void Fl_Cairo_Graphics_Driver::pie( int x, int y, int w, int h, double a1, double a2 )
  338. {
  339. cairo_t *cr = Fl::cairo_cc();
  340. add_arc( x, y, w, h, a1, a2, true );
  341. restore_cairo_matrix();
  342. cairo_fill( cr );
  343. set_cairo_matrix();
  344. }
  345. void Fl_Cairo_Graphics_Driver::line( int x1, int y1, int x2, int y2 )
  346. {
  347. cairo_t *cr = Fl::cairo_cc();
  348. cairo_set_line_width( cr, lw );
  349. // restore_cairo_matrix();
  350. if ( x1 == x2 )
  351. {
  352. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  353. /* vertical line */
  354. if ( y1 > y2 )
  355. {
  356. int t = y2;
  357. y2 = y1;
  358. y1 = t;
  359. }
  360. cairo_move_to( cr, VXO( x1 ), VYO( y1 ) );
  361. cairo_line_to( cr, VXO( x2 ), VHO( y2 ) );
  362. }
  363. else if ( y1 == y2 )
  364. {
  365. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  366. /* horizontal line */
  367. cairo_move_to( cr, HXO( x1 ), HYO( y1 ) );
  368. cairo_line_to( cr, HWO( x2 ), HYO( y2 ) );
  369. }
  370. else
  371. {
  372. /* diagonal line */
  373. cairo_move_to( cr, x1 , y1 );
  374. cairo_line_to( cr, x2 , y2 );
  375. }
  376. cairo_stroke( cr );
  377. // set_cairo_matrix();
  378. cairo_set_antialias( cr, aa );
  379. }
  380. void Fl_Cairo_Graphics_Driver::line( int x1, int y1, int x2, int y2, int x3, int y3 )
  381. {
  382. cairo_t *cr = Fl::cairo_cc();
  383. cairo_set_line_width( cr, lw );
  384. if ( lw <= 1 )
  385. {
  386. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  387. }
  388. // restore_cairo_matrix();
  389. cairo_move_to( cr, x1 , y1 );
  390. cairo_line_to( cr, x2 , y2 );
  391. cairo_line_to( cr, x3 , y3 );
  392. cairo_stroke( cr );
  393. // set_cairo_matrix();
  394. cairo_set_antialias( cr, aa );
  395. }
  396. void Fl_Cairo_Graphics_Driver::rect ( int x, int y, int w, int h )
  397. {
  398. cairo_t *cr = Fl::cairo_cc();
  399. cairo_set_line_width( cr, lw );
  400. /* cairo draws lines half inside and half outside of the path... */
  401. /* const double line_width = cairo_get_line_width( cr ); */
  402. /* const double o = line_width / 2.0; */
  403. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  404. // restore_cairo_matrix();
  405. // cairo_rectangle( cr, x + hlw, y + hlw, w - lw - 1, h - lw - 1);
  406. cairo_rectangle( cr, VXO( x ), HYO( y ), w - 1, h - 1 );
  407. cairo_stroke( cr );
  408. // set_cairo_matrix();
  409. cairo_set_antialias( cr, aa );
  410. }
  411. void Fl_Cairo_Graphics_Driver::rectf ( int x, int y, int w, int h )
  412. {
  413. cairo_t *cr = Fl::cairo_cc();
  414. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  415. // restore_cairo_matrix();
  416. /* cairo fills the inside of the path... */
  417. cairo_rectangle( cr, x, y, w, h );
  418. cairo_fill( cr );
  419. // set_cairo_matrix();
  420. cairo_set_antialias( cr, aa );
  421. }
  422. void Fl_Cairo_Graphics_Driver::begin_line ( void )
  423. {
  424. what = LINE;
  425. npoints = 0;
  426. }
  427. void Fl_Cairo_Graphics_Driver::begin_points ( void )
  428. {
  429. what = POINT_;
  430. npoints = 0;
  431. }
  432. void Fl_Cairo_Graphics_Driver::begin_polygon ( void )
  433. {
  434. what = POLYGON;
  435. npoints = 0;
  436. }
  437. void Fl_Cairo_Graphics_Driver::begin_loop ( void )
  438. {
  439. what = LOOP;
  440. npoints = 0;
  441. }
  442. void Fl_Cairo_Graphics_Driver::begin_complex_polygon ( void )
  443. {
  444. what = POLYGON;
  445. npoints = 0;
  446. }
  447. void Fl_Cairo_Graphics_Driver::end_line ( void )
  448. {
  449. cairo_t *cr = Fl::cairo_cc();
  450. if ( lw <= 1 )
  451. {
  452. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  453. }
  454. cairo_set_line_width( cr, lw );
  455. restore_cairo_matrix();
  456. cairo_stroke( cr );
  457. set_cairo_matrix();
  458. cairo_set_antialias( cr, aa );
  459. }
  460. void Fl_Cairo_Graphics_Driver::end_points ( void )
  461. {
  462. cairo_t *cr = Fl::cairo_cc();
  463. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  464. cairo_fill( cr );
  465. cairo_set_antialias( cr, aa );
  466. }
  467. void Fl_Cairo_Graphics_Driver::end_loop ( void )
  468. {
  469. if ( npoints < 3 )
  470. {
  471. end_line();
  472. return;
  473. }
  474. cairo_t *cr = Fl::cairo_cc();
  475. cairo_close_path( cr );
  476. end_line();
  477. }
  478. /* static double last_vertex_x; */
  479. /* static double last_vertex_y; */
  480. void Fl_Cairo_Graphics_Driver::vertex ( double x, double y )
  481. {
  482. cairo_t *cr = Fl::cairo_cc();
  483. if ( !npoints )
  484. cairo_move_to( cr, x, y );
  485. else
  486. cairo_line_to( cr, x, y );
  487. ++npoints;
  488. }
  489. void Fl_Cairo_Graphics_Driver::gap ( void )
  490. {
  491. npoints = 0;
  492. }
  493. void Fl_Cairo_Graphics_Driver::end_complex_polygon ( void )
  494. {
  495. if ( npoints < 3 )
  496. {
  497. end_line();
  498. return;
  499. }
  500. cairo_t *cr = Fl::cairo_cc();
  501. cairo_close_path( cr );
  502. restore_cairo_matrix();
  503. cairo_fill( cr );
  504. set_cairo_matrix();
  505. }
  506. void Fl_Cairo_Graphics_Driver::end_polygon ( void )
  507. {
  508. if ( npoints < 3 )
  509. {
  510. end_line();
  511. return;
  512. }
  513. cairo_t *cr = Fl::cairo_cc();
  514. cairo_close_path( cr );
  515. restore_cairo_matrix();
  516. cairo_fill( cr );
  517. set_cairo_matrix();
  518. }
  519. void Fl_Cairo_Graphics_Driver::curve( double x, double y, double x1, double y1, double x2, double y2, double x3, double y3 )
  520. {
  521. cairo_t *cr = Fl::cairo_cc();
  522. cairo_move_to( cr, x, y );
  523. cairo_curve_to( cr, x1, y1, x2, y2, x3, y3 );
  524. }
  525. void Fl_Cairo_Graphics_Driver::polygon ( int x, int y, int x1, int y1, int x2, int y2 )
  526. {
  527. cairo_t *cr = Fl::cairo_cc();
  528. cairo_move_to( cr, x , y );
  529. cairo_line_to( cr, x1 , y1 );
  530. cairo_line_to( cr, x2 , y2 );
  531. cairo_close_path( cr );
  532. cairo_fill( cr );
  533. }
  534. void Fl_Cairo_Graphics_Driver::polygon ( int x, int y, int x1, int y1, int x2, int y2, int x3, int y3 )
  535. {
  536. cairo_t *cr = Fl::cairo_cc();
  537. cairo_move_to( cr, x , y );
  538. cairo_line_to( cr, x1 , y1 );
  539. cairo_line_to( cr, x2 , y2 );
  540. cairo_line_to( cr, x3 , y3 );
  541. cairo_close_path( cr );
  542. cairo_fill( cr );
  543. }
  544. void Fl_Cairo_Graphics_Driver::loop ( int x, int y, int x1, int y1, int x2, int y2 )
  545. {
  546. cairo_t *cr = Fl::cairo_cc();
  547. cairo_move_to( cr, x , y );
  548. cairo_line_to( cr, x1 , y1 );
  549. cairo_line_to( cr, x2 , y2 );
  550. cairo_close_path( cr );
  551. cairo_stroke( cr );
  552. }
  553. void Fl_Cairo_Graphics_Driver::loop ( int x, int y, int x1, int y1, int x2, int y2, int x3, int y3 )
  554. {
  555. cairo_t *cr = Fl::cairo_cc();
  556. cairo_move_to( cr, x , y );
  557. cairo_line_to( cr, x1 , y1 );
  558. cairo_line_to( cr, x2 , y2 );
  559. cairo_line_to( cr, x3 , y3 );
  560. cairo_close_path( cr );
  561. cairo_stroke( cr );
  562. }
  563. void Fl_Cairo_Graphics_Driver::xyline ( int x, int y, int x1 )
  564. {
  565. cairo_t *cr = Fl::cairo_cc();
  566. cairo_set_line_width( cr, lw );
  567. if ( lw <= 1 )
  568. {
  569. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  570. }
  571. cairo_move_to( cr, HXO( x ), HYO( y ) );
  572. cairo_line_to( cr, HWO( x1 ), HYO( y ) );
  573. cairo_stroke( cr );
  574. cairo_set_antialias( cr, aa );
  575. }
  576. void Fl_Cairo_Graphics_Driver::xyline ( int x, int y, int x1, int y2 )
  577. {
  578. cairo_t *cr = Fl::cairo_cc();
  579. cairo_set_line_width( cr, lw );
  580. if ( lw <= 1 )
  581. {
  582. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  583. }
  584. /* horizontal line */
  585. cairo_move_to( cr, HXO( x ) , HYO( y ) );
  586. cairo_line_to( cr, HWO( x1 ), HYO( y ) );
  587. /* then vertical line */
  588. cairo_line_to( cr, HWO( x1 ) , VYO( y2 ) );
  589. cairo_stroke( cr );
  590. cairo_set_antialias( cr, aa );
  591. }
  592. void Fl_Cairo_Graphics_Driver::xyline ( int x, int y, int x1, int y2, int x3 )
  593. {
  594. cairo_t *cr = Fl::cairo_cc();
  595. if ( lw <= 1 )
  596. {
  597. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  598. }
  599. cairo_move_to( cr, x , y );
  600. cairo_line_to( cr, x1 , y );
  601. cairo_line_to( cr, x1 , y2 );
  602. cairo_line_to( cr, x3 , y2 );
  603. cairo_stroke( cr );
  604. cairo_set_antialias( cr, aa );
  605. }
  606. void Fl_Cairo_Graphics_Driver::yxline ( int x, int y, int y1 )
  607. {
  608. cairo_t *cr = Fl::cairo_cc();
  609. cairo_set_line_width( cr, lw );
  610. if ( lw <= 1 )
  611. {
  612. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  613. }
  614. cairo_move_to( cr, VXO( x ), VHO( y ) );
  615. cairo_line_to( cr, VXO( x ), VYO( y1 ) );
  616. cairo_stroke( cr );
  617. cairo_set_antialias( cr, aa );
  618. }
  619. void Fl_Cairo_Graphics_Driver::yxline ( int x, int y, int y1, int x2 )
  620. {
  621. cairo_t *cr = Fl::cairo_cc();
  622. if ( lw <= 1 )
  623. {
  624. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  625. }
  626. cairo_move_to( cr, x , y );
  627. cairo_line_to( cr, x, y1 );
  628. cairo_line_to( cr, x2, y1 );
  629. cairo_stroke( cr );
  630. cairo_set_antialias( cr, aa );
  631. }
  632. void Fl_Cairo_Graphics_Driver::yxline ( int x, int y, int y1, int x2, int y3 )
  633. {
  634. cairo_t *cr = Fl::cairo_cc();
  635. if ( lw <= 1 )
  636. {
  637. cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE );
  638. }
  639. cairo_move_to( cr, x , y );
  640. cairo_line_to( cr, x , y1 );
  641. cairo_line_to( cr, x2 , y1 );
  642. cairo_line_to( cr, x2 , y3 );
  643. cairo_stroke( cr );
  644. cairo_set_antialias( cr, aa );
  645. }
  646. static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy,
  647. int &X, int &Y, int &W, int &H)
  648. {
  649. fl_clip_box(XP,YP,WP,HP,X,Y,W,H);
  650. cx += X-XP; cy += Y-YP;
  651. // clip the box down to the size of image, quit if empty:
  652. if (cx < 0) {W += cx; X -= cx; cx = 0;}
  653. if (cx+W > w) W = w-cx;
  654. if (W <= 0) return 1;
  655. if (cy < 0) {H += cy; Y -= cy; cy = 0;}
  656. if (cy+H > h) H = h-cy;
  657. if (H <= 0) return 1;
  658. return 0;
  659. }
  660. void
  661. Fl_Cairo_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy)
  662. {
  663. int X, Y, W, H;
  664. // Don't draw an empty image...
  665. if (!img->d() || !img->array) {
  666. // img->draw_empty(XP, YP);
  667. return;
  668. }
  669. if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) {
  670. return;
  671. }
  672. /* if (!img->id_) { */
  673. /* img->id_ = fl_create_offscreen(img->w(), img->h()); */
  674. /* if ((img->d() == 2 || img->d() == 4) ) { */
  675. /* fl_begin_offscreen((Fl_Offscreen)img->id_); */
  676. /* fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); */
  677. /* fl_end_offscreen(); */
  678. /* } */
  679. /* } */
  680. cairo_t *cr = Fl::cairo_cc();
  681. cairo_format_t fmt;
  682. switch (img->d() )
  683. {
  684. case 4:
  685. fmt = CAIRO_FORMAT_ARGB32;
  686. break;
  687. case 3:
  688. fmt = CAIRO_FORMAT_RGB24;
  689. break;
  690. case 1:
  691. fmt = CAIRO_FORMAT_A8;
  692. break;
  693. }
  694. /* cairo_save( cr ); */
  695. /* cairo_reset_clip( cr ); */
  696. cairo_surface_t *image = cairo_image_surface_create_for_data( (unsigned char *)img->array, fmt, img->w(), img->h( ),
  697. cairo_format_stride_for_width( fmt, img->w() ) );
  698. /* cairo_surface_t *image = cairo_image_surface_create_for_data( (unsigned char *)img->array, fmt, img->w(), img->h(), img->ld() ); */
  699. /* cairo_patter_t *pat = cairo_surface_pattern( image ); */
  700. /* cairo_matrix_t matr; */
  701. /* cairo_matrix_scale( &matr, */
  702. cairo_set_source_surface( cr, image, X - cx, Y - cy );
  703. cairo_rectangle( cr, X, Y, W, H );
  704. cairo_fill(cr);
  705. cairo_surface_destroy( image );
  706. /* cairo_restore( cr ); */
  707. }