2 /*******************************************************************************/
3 /* Copyright (C) 2012 Jonathan Moore Liles */
5 /* This program is free software; you can redistribute it and/or modify it */
6 /* under the terms of the GNU Library General Public License as published */
7 /* by the Free Software Foundation; either version 2 of the License, or (at */
8 /* your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
12 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
15 /* You should have received a copy of the GNU General Public License along */
16 /* with This program; see the file COPYING. If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /*******************************************************************************/
21 /* This class emulates the FLTK graphics drawing API using the Cairo
22 * library. The advantage of doing this is that it provides
23 * antialiasing and transparency on X11 for all FLTK widgets.
25 * The implementation inherits from the Xlib driver and attempts to
26 * keep colors, clipping, and matrix transformations in sync, so that
27 * calls to the base Xlib and Cairo routines can be mixed with the
30 * Fonts are still rendered using XFT. And since the FLTK image
31 * drawing implementation already uses XRender, there would seem to be
32 * little advantage to using Cairo for that either.
34 * Alpha values can be encoded into Fl_Color values by using the new
35 * fl_color_add_alpha function--with the caveat that 100% transparency
36 * (an Alpha of 0) is unsupported. This allows existing boxes and
37 * widgets to be drawn with transparency simply by setting their
38 * color() to one with an alpha value encoded.
40 * Antialiasing can be turned on and off with the new
41 * fl_set_antialias() function. However, it should be noted that, even
42 * with antialiasing disabled drawing complex lines and polygons is
43 * still significantly slower with Cairo than with the base FLTK
58 #define HXO(n) ( n + fl_hxo )
59 #define HYO(n) ( n + fl_hyo )
60 #define VXO(n) ( n + fl_vxo )
61 #define VYO(n) ( n + fl_vyo )
62 #define VHO(n) ( n + fl_vho )
63 #define HWO(n) ( n + fl_hwo )
65 #define BSCALE 0.00392156862f
67 Fl_Color
fl_color_add_alpha ( Fl_Color c
, uchar alpha
)
69 if ( !( c
& 0xFFFFFF00 ) )
71 /* this is an indexed color or black */
74 /* this is an indexed color */
77 Fl::get_color( c
, r
, g
, b
);
79 c
= fl_rgb_color( r
, g
, b
);
86 /* sorry, you can't have zero opacity because we don't
87 * have enough bits and it doesn't make much sense anyway */
90 /* hack to represent black */
95 return ( c
& 0xFFFFFF00 ) | alpha
;
99 #include <cairo/cairo.h>
100 #include <FL/Fl_Cairo.H>
101 #include <FL/fl_draw.H>
103 #include <FL/Fl_Device.H>
105 static double lw
= 1;
107 //static cairo_antialias_t aa = CAIRO_ANTIALIAS_GRAY;
109 static int npoints
= 0;
111 cairo_matrix_t
Fl_Cairo_Graphics_Driver::m
;
112 cairo_matrix_t
Fl_Cairo_Graphics_Driver::stack
[FL_MATRIX_STACK_SIZE
];
113 int Fl_Cairo_Graphics_Driver::sptr
;
115 #define cairo_set_antialias( cr, aa )
117 Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver ( ) : Fl_Xlib_Graphics_Driver ()
122 /* void Fl_Cairo_Graphics_Driver::set_current ( void ) */
127 /* unsigned int w, h, bw, d; */
129 /* XGetGeometry( fl_display, fl_window, &root, &x, &y, &w, &h, &bw, &d ); */
131 /* fl_cairo_surface = cairo_create_surface( fl_gc, w, h ); */
133 /* /\* FIXME: how are we going to free this? *\/ */
134 /* fl_cairo_context = cairo_create( fl_cairo_surface ); */
136 /* cairo_surface_destroy( fl_cairo_surface ); */
138 /* fl_cairo_surface = 0; */
142 #define set_cairo_matrix() \
144 cairo_t *cr = fl_cairo_context; \
146 cairo_set_matrix( cr, &m ); \
148 cairo_identity_matrix( cr ); \
151 #define restore_cairo_matrix() \
153 cairo_t *cr = fl_cairo_context; \
154 cairo_identity_matrix( cr ); \
158 void Fl_Cairo_Graphics_Driver::push_matrix ( void )
160 cairo_t
*cr
= Fl::cairo_cc();
162 cairo_get_matrix( cr
, &m
);
164 if (sptr
==FL_MATRIX_STACK_SIZE
)
165 Fl::error("fl_push_matrix(): matrix stack overflow.");
170 void Fl_Cairo_Graphics_Driver::pop_matrix ( void )
173 Fl::error("fl_pop_matrix(): matrix stack underflow.");
180 void Fl_Cairo_Graphics_Driver::translate ( double x
, double y
)
182 cairo_matrix_translate( &m
, x
, y
);
187 void Fl_Cairo_Graphics_Driver::scale ( double x
, double y
)
189 cairo_matrix_scale( &m
, x
, y
);
194 void Fl_Cairo_Graphics_Driver::rotate ( double a
)
196 cairo_matrix_rotate( &m
, a
* ( M_PI
/ 180.0 ) );
201 void Fl_Cairo_Graphics_Driver::mult_matrix ( double a
, double b
, double c
, double d
, double x
, double y
)
205 cairo_matrix_init( &m2
, a
, b
, c
, d
, x
, y
);
207 cairo_matrix_multiply( &m
, &m2
, &m
);
212 void Fl_Cairo_Graphics_Driver::line_style ( int style
, int t
, char* )
214 cairo_t
*cr
= Fl::cairo_cc();
216 if ( t
== 0 || t
== 1 )
220 cairo_device_to_user_distance (cr
, &w1
, &w2
);
221 lw
= w1
> w2
? w1
: w2
;
228 cairo_set_line_width( cr
, lw
);
230 cairo_set_line_cap( cr
, CAIRO_LINE_CAP_BUTT
);
232 if ( style
& FL_DASH
)
234 const double dash
[] = { lw
, lw
};
235 int len
= sizeof(dash
) / sizeof(dash
[0]);
237 cairo_set_dash( cr
, dash
, len
, 0 );
239 else if ( style
& FL_DOT
)
241 const double dash
[] = { lw
, lw
};
242 int len
= sizeof(dash
) / sizeof(dash
[0]);
244 cairo_set_dash( cr
, dash
, len
, 0 );
246 cairo_set_line_cap( cr
, CAIRO_LINE_CAP_ROUND
);
250 cairo_set_dash( cr
, NULL
, 0, 0 );
254 void Fl_Cairo_Graphics_Driver::color ( Fl_Color c
)
258 Fl_Xlib_Graphics_Driver::color( c
);
260 if ( ( c
& 0x000000ff ) && ! ( c
& 0xFFFFFF00 ) )
262 /* color is indexed, get the RGB value */
263 Fl::get_color( c
, r
, g
, b
);
267 /* color( 255, 0, 0, 50 ); */
271 Fl::get_color( c
& 0xFFFFFF00, r
, g
, b
);
273 /* lower 8 bits become alpha. */
274 uchar a
= c
& 0x000000ff;
279 /* /\* HACK to represent black *\/ */
280 /* if ( ( c & 0xFFFFFF00 ) == 0x01010100 ) */
287 void Fl_Cairo_Graphics_Driver::color ( uchar r
, uchar g
, uchar b
)
289 cairo_t
*cr
= Fl::cairo_cc();
291 Fl_Xlib_Graphics_Driver::color( r
, g
, b
);
296 cairo_set_source_rgb( cr
, r
* BSCALE
, g
* BSCALE
, b
* BSCALE
);
299 void fl_set_antialias ( int v
)
303 case FL_ANTIALIAS_DEFAULT
:
304 cairo_set_antialias( cr
, aa
= CAIRO_ANTIALIAS_DEFAULT
);
306 case FL_ANTIALIAS_ON
:
307 cairo_set_antialias( cr
, aa
= CAIRO_ANTIALIAS_GRAY
);
309 case FL_ANTIALIAS_OFF
:
310 cairo_set_antialias( cr
, aa
= CAIRO_ANTIALIAS_NONE
);
316 void Fl_Cairo_Graphics_Driver::color ( Fl_Color c
, uchar a
)
320 Fl::get_color( c
, r
, g
, b
);
322 Fl_Xlib_Graphics_Driver::color( c
);
327 void Fl_Cairo_Graphics_Driver::color (uchar r
, uchar g
, uchar b
, uchar a
)
329 cairo_t
*cr
= Fl::cairo_cc();
331 // Fl_Xlib_Graphics_Driver::color( r, g, b );
336 cairo_set_source_rgba( cr
, r
* BSCALE
, g
* BSCALE
, b
* BSCALE
, a
* BSCALE
);
339 void Fl_Cairo_Graphics_Driver::circle( double x
, double y
, double r
)
341 cairo_t
*cr
= Fl::cairo_cc();
343 cairo_arc( cr
, x
, y
, r
, 0, 2.0f
* M_PI
);
345 restore_cairo_matrix();
347 if ( what
== POLYGON
)
355 /* static void add_arc( int x, int y, int w, int h, double a1, double a2 ) */
357 /* cairo_t *cr = Fl::cairo_cc(); */
359 /* /\* const double line_width = cairo_get_line_width( cr ); *\/ */
361 /* const double cx = x + ( 0.5f * w ); */
362 /* const double cy = y + ( 0.5f * h ); */
364 /* /\* cairo_save( cr ); *\/ */
365 /* /\* cairo_translate( cr, cx, cy ); *\/ */
366 /* /\* cairo_scale( cr, w, h ); *\/ */
368 /* /\* if ( a1 > a2 ) *\/ */
369 /* /\* cairo_arc( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); *\/ */
371 /* /\* cairo_arc_negative( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); *\/ */
374 /* cairo_save( cr ); */
375 /* cairo_translate( cr, cx, cy ); */
376 /* cairo_scale( cr, w - 1, h - 1 ); */
379 /* cairo_arc( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); */
381 /* cairo_arc_negative( cr, 0.0, 0.0, 0.5, a1 * ( -M_PI / 180.0 ), a2 * ( -M_PI / 180.0 )); */
384 /* cairo_restore( cr ); */
387 static void add_arc( int x
, int y
, int w
, int h
, double a1
, double a2
, bool pie
)
389 cairo_t
*cr
= Fl::cairo_cc();
391 double a1R
= a1
* ( M_PI
/ 180.0 );
392 double a2R
= a2
* ( M_PI
/ 180.0 );
394 double cx
= x
+ 0.5 * w
, cy
= y
+ 0.5 * h
;
398 cairo_translate( cr
, cx
, cy
);
399 // cairo_scale( cr, (w - lw), 0 - ((h - lw) ));
400 cairo_scale( cr
, w
, 0 - h
);
403 cairo_arc_negative( cr
, 0.0, 0.0, 0.5, a1R
, a2R
);
405 cairo_arc( cr
, 0.0, 0.0, 0.5, a1R
, a2R
);
409 cairo_line_to( cr
, 0, 0 );
410 cairo_close_path( cr
);
416 void Fl_Cairo_Graphics_Driver::arc( int x
, int y
, int w
, int h
, double a1
, double a2
)
418 cairo_t
*cr
= Fl::cairo_cc();
420 add_arc( x
, y
, w
, h
, a1
, a2
, false );
422 restore_cairo_matrix();
429 void Fl_Cairo_Graphics_Driver::arc( double x
, double y
, double r
, double a1
, double a2
)
431 cairo_t
*cr
= Fl::cairo_cc();
433 cairo_close_path( cr
);
435 cairo_arc( cr
, x
, y
, r
, a1
* ( -M_PI
/ 180.0 ), a2
* ( -M_PI
/ 180.0 ));
438 void Fl_Cairo_Graphics_Driver::pie( int x
, int y
, int w
, int h
, double a1
, double a2
)
440 cairo_t
*cr
= Fl::cairo_cc();
442 add_arc( x
, y
, w
, h
, a1
, a2
, true );
444 restore_cairo_matrix();
451 void Fl_Cairo_Graphics_Driver::line( int x1
, int y1
, int x2
, int y2
)
453 cairo_t
*cr
= Fl::cairo_cc();
455 cairo_set_line_width( cr
, lw
);
457 // restore_cairo_matrix();
461 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
471 cairo_move_to( cr
, VXO( x1
), VYO( y1
) );
472 cairo_line_to( cr
, VXO( x2
), VHO( y2
) );
476 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
477 /* horizontal line */
478 cairo_move_to( cr
, HXO( x1
), HYO( y1
) );
479 cairo_line_to( cr
, HWO( x2
), HYO( y2
) );
484 cairo_move_to( cr
, x1
, y1
);
485 cairo_line_to( cr
, x2
, y2
);
490 // set_cairo_matrix();
492 cairo_set_antialias( cr
, aa
);
495 void Fl_Cairo_Graphics_Driver::line( int x1
, int y1
, int x2
, int y2
, int x3
, int y3
)
497 cairo_t
*cr
= Fl::cairo_cc();
499 cairo_set_line_width( cr
, lw
);
503 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
506 // restore_cairo_matrix();
508 cairo_move_to( cr
, x1
, y1
);
509 cairo_line_to( cr
, x2
, y2
);
510 cairo_line_to( cr
, x3
, y3
);
514 // set_cairo_matrix();
516 cairo_set_antialias( cr
, aa
);
520 void Fl_Cairo_Graphics_Driver::rect ( int x
, int y
, int w
, int h
)
522 cairo_t
*cr
= Fl::cairo_cc();
524 cairo_set_line_width( cr
, lw
);
526 /* cairo draws lines half inside and half outside of the path... */
528 /* const double line_width = cairo_get_line_width( cr ); */
529 /* const double o = line_width / 2.0; */
531 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
533 // restore_cairo_matrix();
535 // cairo_rectangle( cr, x + hlw, y + hlw, w - lw - 1, h - lw - 1);
536 cairo_rectangle( cr
, VXO( x
), HYO( y
), w
- 1, h
- 1 );
541 // set_cairo_matrix();
543 cairo_set_antialias( cr
, aa
);
546 void Fl_Cairo_Graphics_Driver::rectf ( int x
, int y
, int w
, int h
)
548 cairo_t
*cr
= Fl::cairo_cc();
550 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
552 // restore_cairo_matrix();
554 /* cairo fills the inside of the path... */
555 cairo_rectangle( cr
, x
, y
, w
, h
);
559 // set_cairo_matrix();
561 cairo_set_antialias( cr
, aa
);
565 void Fl_Cairo_Graphics_Driver::begin_line ( void )
571 void Fl_Cairo_Graphics_Driver::begin_points ( void )
577 void Fl_Cairo_Graphics_Driver::begin_polygon ( void )
583 void Fl_Cairo_Graphics_Driver::begin_loop ( void )
589 void Fl_Cairo_Graphics_Driver::begin_complex_polygon ( void )
595 void Fl_Cairo_Graphics_Driver::end_line ( void )
597 cairo_t
*cr
= Fl::cairo_cc();
601 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
604 cairo_set_line_width( cr
, lw
);
606 restore_cairo_matrix();
612 cairo_set_antialias( cr
, aa
);
615 void Fl_Cairo_Graphics_Driver::end_points ( void )
617 cairo_t
*cr
= Fl::cairo_cc();
619 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
623 cairo_set_antialias( cr
, aa
);
626 void Fl_Cairo_Graphics_Driver::end_loop ( void )
634 cairo_t
*cr
= Fl::cairo_cc();
635 cairo_close_path( cr
);
640 /* static double last_vertex_x; */
641 /* static double last_vertex_y; */
643 void Fl_Cairo_Graphics_Driver::vertex ( double x
, double y
)
645 cairo_t
*cr
= Fl::cairo_cc();
648 cairo_move_to( cr
, x
, y
);
650 cairo_line_to( cr
, x
, y
);
655 void Fl_Cairo_Graphics_Driver::gap ( void )
660 void Fl_Cairo_Graphics_Driver::end_complex_polygon ( void )
668 cairo_t
*cr
= Fl::cairo_cc();
670 cairo_close_path( cr
);
672 restore_cairo_matrix();
679 void Fl_Cairo_Graphics_Driver::end_polygon ( void )
687 cairo_t
*cr
= Fl::cairo_cc();
689 cairo_close_path( cr
);
691 restore_cairo_matrix();
698 void Fl_Cairo_Graphics_Driver::curve( double x
, double y
, double x1
, double y1
, double x2
, double y2
, double x3
, double y3
)
700 cairo_t
*cr
= Fl::cairo_cc();
702 cairo_move_to( cr
, x
, y
);
703 cairo_curve_to( cr
, x1
, y1
, x2
, y2
, x3
, y3
);
706 void Fl_Cairo_Graphics_Driver::polygon ( int x
, int y
, int x1
, int y1
, int x2
, int y2
)
708 cairo_t
*cr
= Fl::cairo_cc();
710 cairo_move_to( cr
, x
, y
);
711 cairo_line_to( cr
, x1
, y1
);
712 cairo_line_to( cr
, x2
, y2
);
713 cairo_close_path( cr
);
717 void Fl_Cairo_Graphics_Driver::polygon ( int x
, int y
, int x1
, int y1
, int x2
, int y2
, int x3
, int y3
)
719 cairo_t
*cr
= Fl::cairo_cc();
721 cairo_move_to( cr
, x
, y
);
722 cairo_line_to( cr
, x1
, y1
);
723 cairo_line_to( cr
, x2
, y2
);
724 cairo_line_to( cr
, x3
, y3
);
725 cairo_close_path( cr
);
729 void Fl_Cairo_Graphics_Driver::loop ( int x
, int y
, int x1
, int y1
, int x2
, int y2
)
731 cairo_t
*cr
= Fl::cairo_cc();
733 cairo_move_to( cr
, x
, y
);
734 cairo_line_to( cr
, x1
, y1
);
735 cairo_line_to( cr
, x2
, y2
);
736 cairo_close_path( cr
);
740 void Fl_Cairo_Graphics_Driver::loop ( int x
, int y
, int x1
, int y1
, int x2
, int y2
, int x3
, int y3
)
742 cairo_t
*cr
= Fl::cairo_cc();
744 cairo_move_to( cr
, x
, y
);
745 cairo_line_to( cr
, x1
, y1
);
746 cairo_line_to( cr
, x2
, y2
);
747 cairo_line_to( cr
, x3
, y3
);
748 cairo_close_path( cr
);
753 void Fl_Cairo_Graphics_Driver::xyline ( int x
, int y
, int x1
)
755 cairo_t
*cr
= Fl::cairo_cc();
757 cairo_set_line_width( cr
, lw
);
762 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
765 cairo_move_to( cr
, HXO( x
), HYO( y
) );
766 cairo_line_to( cr
, HWO( x1
), HYO( y
) );
770 cairo_set_antialias( cr
, aa
);
773 void Fl_Cairo_Graphics_Driver::xyline ( int x
, int y
, int x1
, int y2
)
775 cairo_t
*cr
= Fl::cairo_cc();
777 cairo_set_line_width( cr
, lw
);
781 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
784 /* horizontal line */
785 cairo_move_to( cr
, HXO( x
) , HYO( y
) );
786 cairo_line_to( cr
, HWO( x1
), HYO( y
) );
787 /* then vertical line */
788 cairo_line_to( cr
, HWO( x1
) , VYO( y2
) );
792 cairo_set_antialias( cr
, aa
);
796 void Fl_Cairo_Graphics_Driver::xyline ( int x
, int y
, int x1
, int y2
, int x3
)
798 cairo_t
*cr
= Fl::cairo_cc();
802 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
805 cairo_move_to( cr
, x
, y
);
806 cairo_line_to( cr
, x1
, y
);
807 cairo_line_to( cr
, x1
, y2
);
808 cairo_line_to( cr
, x3
, y2
);
812 cairo_set_antialias( cr
, aa
);
815 void Fl_Cairo_Graphics_Driver::yxline ( int x
, int y
, int y1
)
817 cairo_t
*cr
= Fl::cairo_cc();
819 cairo_set_line_width( cr
, lw
);
823 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
826 cairo_move_to( cr
, VXO( x
), VHO( y
) );
827 cairo_line_to( cr
, VXO( x
), VYO( y1
) );
831 cairo_set_antialias( cr
, aa
);
834 void Fl_Cairo_Graphics_Driver::yxline ( int x
, int y
, int y1
, int x2
)
836 cairo_t
*cr
= Fl::cairo_cc();
840 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
843 cairo_move_to( cr
, x
, y
);
844 cairo_line_to( cr
, x
, y1
);
845 cairo_line_to( cr
, x2
, y1
);
849 cairo_set_antialias( cr
, aa
);
852 void Fl_Cairo_Graphics_Driver::yxline ( int x
, int y
, int y1
, int x2
, int y3
)
854 cairo_t
*cr
= Fl::cairo_cc();
858 cairo_set_antialias( cr
, CAIRO_ANTIALIAS_NONE
);
861 cairo_move_to( cr
, x
, y
);
862 cairo_line_to( cr
, x
, y1
);
863 cairo_line_to( cr
, x2
, y1
);
864 cairo_line_to( cr
, x2
, y3
);
868 cairo_set_antialias( cr
, aa
);
871 static int start(Fl_RGB_Image
*img
, int XP
, int YP
, int WP
, int HP
, int w
, int h
, int &cx
, int &cy
,
872 int &X
, int &Y
, int &W
, int &H
)
874 fl_clip_box(XP
,YP
,WP
,HP
,X
,Y
,W
,H
);
876 cx
+= X
-XP
; cy
+= Y
-YP
;
877 // clip the box down to the size of image, quit if empty:
878 if (cx
< 0) {W
+= cx
; X
-= cx
; cx
= 0;}
879 if (cx
+W
> w
) W
= w
-cx
;
880 if (W
<= 0) return 1;
881 if (cy
< 0) {H
+= cy
; Y
-= cy
; cy
= 0;}
882 if (cy
+H
> h
) H
= h
-cy
;
883 if (H
<= 0) return 1;
889 Fl_Cairo_Graphics_Driver::draw(Fl_RGB_Image
*img
, int XP
, int YP
, int WP
, int HP
, int cx
, int cy
)
893 // Don't draw an empty image...
894 if (!img
->d() || !img
->array
) {
895 // img->draw_empty(XP, YP);
899 if (start(img
, XP
, YP
, WP
, HP
, img
->w(), img
->h(), cx
, cy
, X
, Y
, W
, H
)) {
903 /* if (!img->id_) { */
904 /* img->id_ = fl_create_offscreen(img->w(), img->h()); */
905 /* if ((img->d() == 2 || img->d() == 4) ) { */
906 /* fl_begin_offscreen((Fl_Offscreen)img->id_); */
907 /* fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); */
908 /* fl_end_offscreen(); */
912 cairo_t
*cr
= Fl::cairo_cc();
914 cairo_format_t fmt
= CAIRO_FORMAT_ARGB32
;
919 fmt
= CAIRO_FORMAT_ARGB32
;
922 fmt
= CAIRO_FORMAT_RGB24
;
925 fmt
= CAIRO_FORMAT_A8
;
929 /* cairo_save( cr ); */
931 /* cairo_reset_clip( cr ); */
933 cairo_surface_t
*image
= cairo_image_surface_create_for_data( (unsigned char *)img
->array
, fmt
, img
->w(), img
->h( ),
934 cairo_format_stride_for_width( fmt
, img
->w() ) );
936 /* cairo_surface_t *image = cairo_image_surface_create_for_data( (unsigned char *)img->array, fmt, img->w(), img->h(), img->ld() ); */
939 /* cairo_patter_t *pat = cairo_surface_pattern( image ); */
941 /* cairo_matrix_t matr; */
943 /* cairo_matrix_scale( &matr, */
945 cairo_set_source_surface( cr
, image
, X
- cx
, Y
- cy
);
947 cairo_rectangle( cr
, X
, Y
, W
, H
);
951 cairo_surface_destroy( image
);
953 /* cairo_restore( cr ); */