1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/graphicc.cpp
3 // Purpose: cairo device context class
4 // Author: Stefan Csomor
8 // Copyright: (c) 2006 Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
22 #include "wx/window.h"
25 #include "wx/dialog.h"
27 #include "wx/bitmap.h"
28 #include "wx/dcmemory.h"
31 #include "wx/dcprint.h"
32 #include "wx/module.h"
36 #include "wx/gtk/win_gtk.h"
39 #include "wx/graphics.h"
41 #if wxUSE_GRAPHICS_CONTEXT
47 //-----------------------------------------------------------------------------
49 //-----------------------------------------------------------------------------
51 const double RAD2DEG
= 180.0 / M_PI
;
53 //-----------------------------------------------------------------------------
55 //-----------------------------------------------------------------------------
57 static inline double dmin(double a
, double b
)
61 static inline double dmax(double a
, double b
)
66 static inline double DegToRad(double deg
)
68 return (deg
* M_PI
) / 180.0;
70 static inline double RadToDeg(double deg
)
72 return (deg
* 180.0) / M_PI
;
75 //-----------------------------------------------------------------------------
76 // device context implementation
78 // more and more of the dc functionality should be implemented by calling
79 // the appropricate wxCairoContext, but we will have to do that step by step
80 // also coordinate conversions should be moved to native matrix ops
81 //-----------------------------------------------------------------------------
83 // we always stock two context states, one at entry, to be able to preserve the
84 // state we were called with, the other one after changing to HI Graphics orientation
85 // (this one is used for getting back clippings etc)
87 //-----------------------------------------------------------------------------
88 // wxGraphicsPath implementation
89 //-----------------------------------------------------------------------------
91 // TODO remove this dependency (gdiplus needs the macros)
94 #define max(a,b) (((a) > (b)) ? (a) : (b))
98 #define min(a,b) (((a) < (b)) ? (a) : (b))
106 class WXDLLIMPEXP_CORE wxCairoPathData
: public wxGraphicsPathData
109 wxCairoPathData(wxGraphicsRenderer
* renderer
, cairo_t
* path
= NULL
);
112 virtual wxGraphicsObjectRefData
*Clone() const;
115 // These are the path primitives from which everything else can be constructed
118 // begins a new subpath at (x,y)
119 virtual void MoveToPoint( wxDouble x
, wxDouble y
);
121 // adds a straight line from the current point to (x,y)
122 virtual void AddLineToPoint( wxDouble x
, wxDouble y
);
124 // adds a cubic Bezier curve from the current point, using two control points and an end point
125 virtual void AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
);
128 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
129 virtual void AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise
) ;
131 // gets the last point of the current path, (0,0) if not yet set
132 virtual void GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const;
135 virtual void AddPath( const wxGraphicsPathData
* path
);
137 // closes the current sub-path
138 virtual void CloseSubpath();
141 // These are convenience functions which - if not available natively will be assembled
142 // using the primitives from above
147 // appends a rectangle as a new closed subpath
148 virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) ;
149 // appends an ellipsis as a new closed subpath fitting the passed rectangle
150 virtual void AddEllipsis( wxDouble x, wxDouble y, wxDouble w , wxDouble h ) ;
152 // draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
153 virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r ) ;
156 // returns the native path
157 virtual void * GetNativePath() const ;
159 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
160 virtual void UnGetNativePath(void *p
) const;
162 // transforms each point of this path by the matrix
163 virtual void Transform( const wxGraphicsMatrixData
* matrix
) ;
165 // gets the bounding box enclosing all points (possibly including control points)
166 virtual void GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*h
) const;
168 virtual bool Contains( wxDouble x
, wxDouble y
, int fillStyle
= wxWINDING_RULE
) const;
171 cairo_t
* m_pathContext
;
174 class WXDLLIMPEXP_CORE wxCairoMatrixData
: public wxGraphicsMatrixData
177 wxCairoMatrixData(wxGraphicsRenderer
* renderer
, const cairo_matrix_t
* matrix
= NULL
) ;
178 virtual ~wxCairoMatrixData() ;
180 virtual wxGraphicsObjectRefData
*Clone() const ;
182 // concatenates the matrix
183 virtual void Concat( const wxGraphicsMatrixData
*t
);
185 // sets the matrix to the respective values
186 virtual void Set(wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
187 wxDouble tx
=0.0, wxDouble ty
=0.0);
189 // gets the component valuess of the matrix
190 virtual void Get(wxDouble
* a
=NULL
, wxDouble
* b
=NULL
, wxDouble
* c
=NULL
,
191 wxDouble
* d
=NULL
, wxDouble
* tx
=NULL
, wxDouble
* ty
=NULL
) const;
193 // makes this the inverse matrix
194 virtual void Invert();
196 // returns true if the elements of the transformation matrix are equal ?
197 virtual bool IsEqual( const wxGraphicsMatrixData
* t
) const ;
199 // return true if this is the identity matrix
200 virtual bool IsIdentity() const;
206 // add the translation to this matrix
207 virtual void Translate( wxDouble dx
, wxDouble dy
);
209 // add the scale to this matrix
210 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
212 // add the rotation to this matrix (radians)
213 virtual void Rotate( wxDouble angle
);
216 // apply the transforms
219 // applies that matrix to the point
220 virtual void TransformPoint( wxDouble
*x
, wxDouble
*y
) const;
222 // applies the matrix except for translations
223 virtual void TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const;
225 // returns the native representation
226 virtual void * GetNativeMatrix() const;
228 cairo_matrix_t m_matrix
;
231 class WXDLLIMPEXP_CORE wxCairoPenData
: public wxGraphicsObjectRefData
234 wxCairoPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
);
239 virtual void Apply( wxGraphicsContext
* context
);
240 virtual wxDouble
GetWidth() { return m_width
; }
250 cairo_line_cap_t m_cap
;
251 cairo_line_join_t m_join
;
254 const double *m_lengths
;
255 double *m_userLengths
;
260 class WXDLLIMPEXP_CORE wxCairoBrushData
: public wxGraphicsObjectRefData
263 wxCairoBrushData( wxGraphicsRenderer
* renderer
);
264 wxCairoBrushData( wxGraphicsRenderer
* renderer
, const wxBrush
&brush
);
265 ~wxCairoBrushData ();
267 virtual void Apply( wxGraphicsContext
* context
);
268 void CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
269 const wxColour
&c1
, const wxColour
&c2
);
270 void CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
271 const wxColour
&oColor
, const wxColour
&cColor
);
282 cairo_pattern_t
* m_brushPattern
;
285 class wxCairoFontData
: public wxGraphicsObjectRefData
288 wxCairoFontData( wxGraphicsRenderer
* renderer
, const wxFont
&font
, const wxColour
& col
);
291 virtual void Apply( wxGraphicsContext
* context
);
293 wxCharBuffer m_fontName
;
295 cairo_font_slant_t m_slant
;
296 cairo_font_weight_t m_weight
;
303 class WXDLLIMPEXP_CORE wxCairoContext
: public wxGraphicsContext
305 DECLARE_NO_COPY_CLASS(wxCairoContext
)
308 wxCairoContext( wxGraphicsRenderer
* renderer
, const wxWindowDC
& dc
);
310 wxCairoContext( wxGraphicsRenderer
* renderer
, GdkDrawable
*drawable
);
312 wxCairoContext( wxGraphicsRenderer
* renderer
, cairo_t
*context
);
313 wxCairoContext( wxGraphicsRenderer
* renderer
, wxWindow
*window
);
315 virtual ~wxCairoContext();
317 virtual void Clip( const wxRegion
®ion
);
319 // clips drawings to the rect
320 virtual void Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
322 // resets the clipping to original extent
323 virtual void ResetClip();
325 virtual void * GetNativeContext();
327 virtual void StrokePath( const wxGraphicsPath
& p
);
328 virtual void FillPath( const wxGraphicsPath
& p
, int fillStyle
= wxWINDING_RULE
);
330 virtual void Translate( wxDouble dx
, wxDouble dy
);
331 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
332 virtual void Rotate( wxDouble angle
);
334 // concatenates this transform with the current transform of this context
335 virtual void ConcatTransform( const wxGraphicsMatrix
& matrix
);
337 // sets the transform of this context
338 virtual void SetTransform( const wxGraphicsMatrix
& matrix
);
340 // gets the matrix of this context
341 virtual wxGraphicsMatrix
GetTransform() const;
343 virtual void DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
344 virtual void DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
345 virtual void PushState();
346 virtual void PopState();
348 virtual void DrawText( const wxString
&str
, wxDouble x
, wxDouble y
);
349 virtual void GetTextExtent( const wxString
&str
, wxDouble
*width
, wxDouble
*height
,
350 wxDouble
*descent
, wxDouble
*externalLeading
) const;
351 virtual void GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const;
357 //-----------------------------------------------------------------------------
358 // wxCairoPenData implementation
359 //-----------------------------------------------------------------------------
361 wxCairoPenData::~wxCairoPenData()
363 delete[] m_userLengths
;
366 void wxCairoPenData::Init()
369 m_userLengths
= NULL
;
374 wxCairoPenData::wxCairoPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
)
375 : wxGraphicsObjectRefData(renderer
)
379 m_width
= m_pen
.GetWidth();
383 m_red
= m_pen
.GetColour().Red()/255.0;
384 m_green
= m_pen
.GetColour().Green()/255.0;
385 m_blue
= m_pen
.GetColour().Blue()/255.0;
386 m_alpha
= m_pen
.GetColour().Alpha()/255.0;
388 switch ( m_pen
.GetCap() )
391 m_cap
= CAIRO_LINE_CAP_ROUND
;
394 case wxCAP_PROJECTING
:
395 m_cap
= CAIRO_LINE_CAP_SQUARE
;
399 m_cap
= CAIRO_LINE_CAP_BUTT
;
403 m_cap
= CAIRO_LINE_CAP_BUTT
;
407 switch ( m_pen
.GetJoin() )
410 m_join
= CAIRO_LINE_JOIN_BEVEL
;
414 m_join
= CAIRO_LINE_JOIN_MITER
;
418 m_join
= CAIRO_LINE_JOIN_ROUND
;
422 m_join
= CAIRO_LINE_JOIN_MITER
;
426 const double dashUnit
= m_width
< 1.0 ? 1.0 : m_width
;
427 const double dotted
[] =
429 dashUnit
, dashUnit
+ 2.0
431 static const double short_dashed
[] =
435 static const double dashed
[] =
439 static const double dotted_dashed
[] =
441 9.0 , 6.0 , 3.0 , 3.0
444 switch ( m_pen
.GetStyle() )
450 m_count
= WXSIZEOF(dotted
);
451 m_userLengths
= new double[ m_count
] ;
452 memcpy( m_userLengths
, dotted
, sizeof(dotted
) );
453 m_lengths
= m_userLengths
;
458 m_count
= WXSIZEOF(dashed
);
463 m_count
= WXSIZEOF(short_dashed
);
468 m_count
= WXSIZEOF(dotted_dashed
);
474 m_count
= m_pen
.GetDashes( &wxdashes
) ;
475 if ((wxdashes
!= NULL
) && (m_count
> 0))
477 m_userLengths
= new double[m_count
] ;
478 for ( int i
= 0 ; i
< m_count
; ++i
)
480 m_userLengths
[i
] = wxdashes
[i
] * dashUnit
;
482 if ( i
% 2 == 1 && m_userLengths
[i
] < dashUnit
+ 2.0 )
483 m_userLengths
[i
] = dashUnit
+ 2.0 ;
484 else if ( i
% 2 == 0 && m_userLengths
[i
] < dashUnit
)
485 m_userLengths
[i
] = dashUnit
;
488 m_lengths
= m_userLengths
;
494 wxBitmap* bmp = pen.GetStipple();
495 if ( bmp && bmp->Ok() )
497 wxDELETE( m_penImage );
498 wxDELETE( m_penBrush );
499 m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE());
500 m_penBrush = new TextureBrush(m_penImage);
501 m_pen->SetBrush( m_penBrush );
507 if ( m_pen
.GetStyle() >= wxFIRST_HATCH
&& m_pen
.GetStyle() <= wxLAST_HATCH
)
510 wxDELETE( m_penBrush );
511 HatchStyle style = HatchStyleHorizontal;
512 switch( pen.GetStyle() )
514 case wxBDIAGONAL_HATCH :
515 style = HatchStyleBackwardDiagonal;
517 case wxCROSSDIAG_HATCH :
518 style = HatchStyleDiagonalCross;
520 case wxFDIAGONAL_HATCH :
521 style = HatchStyleForwardDiagonal;
524 style = HatchStyleCross;
526 case wxHORIZONTAL_HATCH :
527 style = HatchStyleHorizontal;
529 case wxVERTICAL_HATCH :
530 style = HatchStyleVertical;
534 m_penBrush = new HatchBrush(style,Color( pen.GetColour().Alpha() , pen.GetColour().Red() ,
535 pen.GetColour().Green() , pen.GetColour().Blue() ), Color.Transparent );
536 m_pen->SetBrush( m_penBrush )
543 void wxCairoPenData::Apply( wxGraphicsContext
* context
)
545 cairo_t
* ctext
= (cairo_t
*) context
->GetNativeContext();
546 cairo_set_line_width(ctext
,m_width
);
547 cairo_set_source_rgba(ctext
,m_red
,m_green
, m_blue
,m_alpha
);
548 cairo_set_line_cap(ctext
,m_cap
);
549 cairo_set_line_join(ctext
,m_join
);
550 cairo_set_dash(ctext
,(double*)m_lengths
,m_count
,0.0);
553 //-----------------------------------------------------------------------------
554 // wxCairoBrushData implementation
555 //-----------------------------------------------------------------------------
557 wxCairoBrushData::wxCairoBrushData( wxGraphicsRenderer
* renderer
)
558 : wxGraphicsObjectRefData( renderer
)
563 wxCairoBrushData::wxCairoBrushData( wxGraphicsRenderer
* renderer
, const wxBrush
&brush
)
564 : wxGraphicsObjectRefData(renderer
)
568 m_red
= brush
.GetColour().Red()/255.0;
569 m_green
= brush
.GetColour().Green()/255.0;
570 m_blue
= brush
.GetColour().Blue()/255.0;
571 m_alpha
= brush
.GetColour().Alpha()/255.0;
573 if ( brush.GetStyle() == wxSOLID)
575 m_brush = new SolidBrush( Color( brush.GetColour().Alpha() , brush.GetColour().Red() ,
576 brush.GetColour().Green() , brush.GetColour().Blue() ) );
578 else if ( brush.IsHatch() )
580 HatchStyle style = HatchStyleHorizontal;
581 switch( brush.GetStyle() )
583 case wxBDIAGONAL_HATCH :
584 style = HatchStyleBackwardDiagonal;
586 case wxCROSSDIAG_HATCH :
587 style = HatchStyleDiagonalCross;
589 case wxFDIAGONAL_HATCH :
590 style = HatchStyleForwardDiagonal;
593 style = HatchStyleCross;
595 case wxHORIZONTAL_HATCH :
596 style = HatchStyleHorizontal;
598 case wxVERTICAL_HATCH :
599 style = HatchStyleVertical;
603 m_brush = new HatchBrush(style,Color( brush.GetColour().Alpha() , brush.GetColour().Red() ,
604 brush.GetColour().Green() , brush.GetColour().Blue() ), Color.Transparent );
608 wxBitmap* bmp = brush.GetStipple();
609 if ( bmp && bmp->Ok() )
611 wxDELETE( m_brushImage );
612 m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE());
613 m_brush = new TextureBrush(m_brushImage);
619 wxCairoBrushData::~wxCairoBrushData ()
622 cairo_pattern_destroy(m_brushPattern
);
625 void wxCairoBrushData::Apply( wxGraphicsContext
* context
)
627 cairo_t
* ctext
= (cairo_t
*) context
->GetNativeContext();
628 if ( m_brushPattern
)
630 cairo_set_source(ctext
,m_brushPattern
);
634 cairo_set_source_rgba(ctext
,m_red
,m_green
, m_blue
,m_alpha
);
638 void wxCairoBrushData::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
639 const wxColour
&c1
, const wxColour
&c2
)
641 m_brushPattern
= cairo_pattern_create_linear(x1
,y1
,x2
,y2
);
642 cairo_pattern_add_color_stop_rgba(m_brushPattern
,0.0,c1
.Red()/255.0,
643 c1
.Green()/255.0, c1
.Blue()/255.0,c1
.Alpha()/255.0);
644 cairo_pattern_add_color_stop_rgba(m_brushPattern
,1.0,c2
.Red()/255.0,
645 c2
.Green()/255.0, c2
.Blue()/255.0,c2
.Alpha()/255.0);
646 wxASSERT_MSG(cairo_pattern_status(m_brushPattern
) == CAIRO_STATUS_SUCCESS
, wxT("Couldn't create cairo pattern"));
649 void wxCairoBrushData::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
650 const wxColour
&oColor
, const wxColour
&cColor
)
652 m_brushPattern
= cairo_pattern_create_radial(xo
,yo
,0.0,xc
,yc
,radius
);
653 cairo_pattern_add_color_stop_rgba(m_brushPattern
,0.0,oColor
.Red()/255.0,
654 oColor
.Green()/255.0, oColor
.Blue()/255.0,oColor
.Alpha()/255.0);
655 cairo_pattern_add_color_stop_rgba(m_brushPattern
,1.0,cColor
.Red()/255.0,
656 cColor
.Green()/255.0, cColor
.Blue()/255.0,cColor
.Alpha()/255.0);
657 wxASSERT_MSG(cairo_pattern_status(m_brushPattern
) == CAIRO_STATUS_SUCCESS
, wxT("Couldn't create cairo pattern"));
660 void wxCairoBrushData::Init()
662 m_brushPattern
= NULL
;
665 //-----------------------------------------------------------------------------
666 // wxCairoFontData implementation
667 //-----------------------------------------------------------------------------
669 wxCairoFontData::wxCairoFontData( wxGraphicsRenderer
* renderer
, const wxFont
&font
,
670 const wxColour
& col
) : wxGraphicsObjectRefData(renderer
)
672 m_red
= col
.Red()/255.0;
673 m_green
= col
.Green()/255.0;
674 m_blue
= col
.Blue()/255.0;
675 m_alpha
= col
.Alpha()/255.0;
677 m_size
= font
.GetPointSize();
678 m_fontName
= font
.GetFaceName().mb_str(wxConvUTF8
);
679 m_slant
= font
.GetStyle() == wxFONTSTYLE_ITALIC
? CAIRO_FONT_SLANT_ITALIC
:CAIRO_FONT_SLANT_NORMAL
;
680 m_weight
= font
.GetWeight() == wxFONTWEIGHT_BOLD
? CAIRO_FONT_WEIGHT_BOLD
:CAIRO_FONT_WEIGHT_NORMAL
;
683 wxCairoFontData::~wxCairoFontData()
687 void wxCairoFontData::Apply( wxGraphicsContext
* context
)
689 cairo_t
* ctext
= (cairo_t
*) context
->GetNativeContext();
690 cairo_set_source_rgba(ctext
,m_red
,m_green
, m_blue
,m_alpha
);
691 cairo_select_font_face(ctext
,m_fontName
,m_slant
,m_weight
);
692 cairo_set_font_size(ctext
,m_size
);
697 //-----------------------------------------------------------------------------
698 // wxCairoPathData implementation
699 //-----------------------------------------------------------------------------
701 wxCairoPathData::wxCairoPathData( wxGraphicsRenderer
* renderer
, cairo_t
* pathcontext
)
702 : wxGraphicsPathData(renderer
)
706 m_pathContext
= pathcontext
;
710 cairo_surface_t
* surface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
,1,1);
711 m_pathContext
= cairo_create(surface
);
712 cairo_surface_destroy (surface
);
716 wxCairoPathData::~wxCairoPathData()
718 cairo_destroy(m_pathContext
);
721 wxGraphicsObjectRefData
*wxCairoPathData::Clone() const
723 cairo_surface_t
* surface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
,1,1);
724 cairo_t
* pathcontext
= cairo_create(surface
);
725 cairo_surface_destroy (surface
);
727 cairo_path_t
* path
= cairo_copy_path(m_pathContext
);
728 cairo_append_path(pathcontext
, path
);
729 cairo_path_destroy(path
);
730 return new wxCairoPathData( GetRenderer() ,pathcontext
);
734 void* wxCairoPathData::GetNativePath() const
736 return cairo_copy_path(m_pathContext
) ;
739 void wxCairoPathData::UnGetNativePath(void *p
) const
741 cairo_path_destroy((cairo_path_t
*)p
);
748 void wxCairoPathData::MoveToPoint( wxDouble x
, wxDouble y
)
750 cairo_move_to(m_pathContext
,x
,y
);
753 void wxCairoPathData::AddLineToPoint( wxDouble x
, wxDouble y
)
755 cairo_line_to(m_pathContext
,x
,y
);
758 void wxCairoPathData::AddPath( const wxGraphicsPathData
* path
)
763 void wxCairoPathData::CloseSubpath()
765 cairo_close_path(m_pathContext
);
768 void wxCairoPathData::AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
)
770 cairo_curve_to(m_pathContext
,cx1
,cy1
,cx2
,cy2
,x
,y
);
773 // gets the last point of the current path, (0,0) if not yet set
774 void wxCairoPathData::GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const
777 cairo_get_current_point(m_pathContext
,&dx
,&dy
);
784 void wxCairoPathData::AddArc( wxDouble x
, wxDouble y
, wxDouble r
, double startAngle
, double endAngle
, bool clockwise
)
786 // as clockwise means positive in our system (y pointing downwards)
787 // TODO make this interpretation dependent of the
789 if ( clockwise
||(endAngle
-startAngle
)>=2*M_PI
)
790 cairo_arc(m_pathContext
,x
,y
,r
,startAngle
,endAngle
);
792 cairo_arc_negative(m_pathContext
,x
,y
,r
,startAngle
,endAngle
);
795 // transforms each point of this path by the matrix
796 void wxCairoPathData::Transform( const wxGraphicsMatrixData
* matrix
)
798 // as we don't have a true path object, we have to apply the inverse
799 // matrix to the context
800 cairo_matrix_t m
= *((cairo_matrix_t
*) matrix
->GetNativeMatrix());
801 cairo_matrix_invert( &m
);
802 cairo_transform(m_pathContext
,&m
);
805 // gets the bounding box enclosing all points (possibly including control points)
806 void wxCairoPathData::GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*h
) const
810 cairo_stroke_extents( m_pathContext
, &x1
, &y1
, &x2
, &y2
);
834 bool wxCairoPathData::Contains( wxDouble x
, wxDouble y
, int fillStyle
) const
836 return cairo_in_stroke( m_pathContext
, x
, y
) != 0;
839 //-----------------------------------------------------------------------------
840 // wxCairoMatrixData implementation
841 //-----------------------------------------------------------------------------
843 wxCairoMatrixData::wxCairoMatrixData(wxGraphicsRenderer
* renderer
, const cairo_matrix_t
* matrix
)
844 : wxGraphicsMatrixData(renderer
)
850 wxCairoMatrixData::~wxCairoMatrixData()
855 wxGraphicsObjectRefData
*wxCairoMatrixData::Clone() const
857 return new wxCairoMatrixData(GetRenderer(),&m_matrix
);
860 // concatenates the matrix
861 void wxCairoMatrixData::Concat( const wxGraphicsMatrixData
*t
)
863 cairo_matrix_multiply( &m_matrix
, &m_matrix
, (cairo_matrix_t
*) t
->GetNativeMatrix());
866 // sets the matrix to the respective values
867 void wxCairoMatrixData::Set(wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
868 wxDouble tx
, wxDouble ty
)
870 cairo_matrix_init( &m_matrix
, a
, b
, c
, d
, tx
, ty
);
873 // gets the component valuess of the matrix
874 void wxCairoMatrixData::Get(wxDouble
* a
, wxDouble
* b
, wxDouble
* c
,
875 wxDouble
* d
, wxDouble
* tx
, wxDouble
* ty
) const
877 if (a
) *a
= m_matrix
.xx
;
878 if (b
) *b
= m_matrix
.yx
;
879 if (c
) *c
= m_matrix
.xy
;
880 if (d
) *d
= m_matrix
.yy
;
881 if (tx
) *tx
= m_matrix
.x0
;
882 if (ty
) *ty
= m_matrix
.y0
;
885 // makes this the inverse matrix
886 void wxCairoMatrixData::Invert()
888 cairo_matrix_invert( &m_matrix
);
891 // returns true if the elements of the transformation matrix are equal ?
892 bool wxCairoMatrixData::IsEqual( const wxGraphicsMatrixData
* t
) const
894 const cairo_matrix_t
* tm
= (cairo_matrix_t
*) t
->GetNativeMatrix();
896 m_matrix
.xx
== tm
->xx
&&
897 m_matrix
.yx
== tm
->yx
&&
898 m_matrix
.xy
== tm
->xy
&&
899 m_matrix
.yy
== tm
->yy
&&
900 m_matrix
.x0
== tm
->x0
&&
901 m_matrix
.y0
== tm
->y0
) ;
904 // return true if this is the identity matrix
905 bool wxCairoMatrixData::IsIdentity() const
907 return ( m_matrix
.xx
== 1 && m_matrix
.yy
== 1 &&
908 m_matrix
.yx
== 0 && m_matrix
.xy
== 0 && m_matrix
.x0
== 0 && m_matrix
.y0
== 0);
915 // add the translation to this matrix
916 void wxCairoMatrixData::Translate( wxDouble dx
, wxDouble dy
)
918 cairo_matrix_translate( &m_matrix
, dx
, dy
) ;
921 // add the scale to this matrix
922 void wxCairoMatrixData::Scale( wxDouble xScale
, wxDouble yScale
)
924 cairo_matrix_scale( &m_matrix
, xScale
, yScale
) ;
927 // add the rotation to this matrix (radians)
928 void wxCairoMatrixData::Rotate( wxDouble angle
)
930 cairo_matrix_rotate( &m_matrix
, angle
) ;
934 // apply the transforms
937 // applies that matrix to the point
938 void wxCairoMatrixData::TransformPoint( wxDouble
*x
, wxDouble
*y
) const
940 double lx
= *x
, ly
= *y
;
941 cairo_matrix_transform_point( &m_matrix
, &lx
, &ly
);
946 // applies the matrix except for translations
947 void wxCairoMatrixData::TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const
949 double lx
= *dx
, ly
= *dy
;
950 cairo_matrix_transform_distance( &m_matrix
, &lx
, &ly
);
955 // returns the native representation
956 void * wxCairoMatrixData::GetNativeMatrix() const
958 return (void*) &m_matrix
;
961 //-----------------------------------------------------------------------------
962 // wxCairoContext implementation
963 //-----------------------------------------------------------------------------
965 wxCairoContext::wxCairoContext( wxGraphicsRenderer
* renderer
, const wxWindowDC
& dc
)
966 : wxGraphicsContext(renderer
)
969 m_context
= gdk_cairo_create( dc
.m_window
) ;
976 wxCairoContext::wxCairoContext( wxGraphicsRenderer
* renderer
, GdkDrawable
*drawable
)
977 : wxGraphicsContext(renderer
)
979 m_context
= gdk_cairo_create( drawable
) ;
985 wxCairoContext::wxCairoContext( wxGraphicsRenderer
* renderer
, cairo_t
*context
)
986 : wxGraphicsContext(renderer
)
988 m_context
= context
;
993 wxCairoContext::wxCairoContext( wxGraphicsRenderer
* renderer
, wxWindow
*window
)
994 : wxGraphicsContext(renderer
)
997 // something along these lines (copied from dcclient)
999 GtkWidget
*widget
= window
->m_wxwindow
;
1001 // Some controls don't have m_wxwindow - like wxStaticBox, but the user
1002 // code should still be able to create wxClientDCs for them, so we will
1003 // use the parent window here then.
1006 window
= window
->GetParent();
1007 widget
= window
->m_wxwindow
;
1010 wxASSERT_MSG( widget
, wxT("wxCairoContext needs a widget") );
1012 GtkPizza
*pizza
= GTK_PIZZA( widget
);
1013 GdkDrawable
* drawable
= pizza
->bin_window
;
1014 m_context
= gdk_cairo_create( drawable
) ;
1020 wxCairoContext::~wxCairoContext()
1026 cairo_destroy(m_context
);
1031 void wxCairoContext::Clip( const wxRegion
& WXUNUSED(region
) )
1036 void wxCairoContext::Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1041 void wxCairoContext::ResetClip()
1047 void wxCairoContext::StrokePath( const wxGraphicsPath
& path
)
1049 if ( !m_pen
.IsNull() )
1051 cairo_path_t
* cp
= (cairo_path_t
*) path
.GetNativePath() ;
1052 cairo_append_path(m_context
,cp
);
1053 ((wxCairoPenData
*)m_pen
.GetRefData())->Apply(this);
1054 cairo_stroke(m_context
);
1055 path
.UnGetNativePath(cp
);
1059 void wxCairoContext::FillPath( const wxGraphicsPath
& path
, int fillStyle
)
1061 if ( !m_brush
.IsNull() )
1063 cairo_path_t
* cp
= (cairo_path_t
*) path
.GetNativePath() ;
1064 cairo_append_path(m_context
,cp
);
1065 ((wxCairoBrushData
*)m_brush
.GetRefData())->Apply(this);
1066 cairo_set_fill_rule(m_context
,fillStyle
==wxODDEVEN_RULE
? CAIRO_FILL_RULE_EVEN_ODD
: CAIRO_FILL_RULE_WINDING
);
1067 cairo_fill(m_context
);
1068 path
.UnGetNativePath(cp
);
1072 void wxCairoContext::Rotate( wxDouble angle
)
1074 cairo_rotate(m_context
,angle
);
1077 void wxCairoContext::Translate( wxDouble dx
, wxDouble dy
)
1079 cairo_translate(m_context
,dx
,dy
);
1082 void wxCairoContext::Scale( wxDouble xScale
, wxDouble yScale
)
1084 cairo_scale(m_context
,xScale
,yScale
);
1087 // concatenates this transform with the current transform of this context
1088 void wxCairoContext::ConcatTransform( const wxGraphicsMatrix
& matrix
)
1090 cairo_transform(m_context
,(const cairo_matrix_t
*) matrix
.GetNativeMatrix());
1093 // sets the transform of this context
1094 void wxCairoContext::SetTransform( const wxGraphicsMatrix
& matrix
)
1096 cairo_set_matrix(m_context
,(const cairo_matrix_t
*) matrix
.GetNativeMatrix());
1099 // gets the matrix of this context
1100 wxGraphicsMatrix
wxCairoContext::GetTransform() const
1102 wxGraphicsMatrix matrix
= CreateMatrix();
1103 cairo_get_matrix(m_context
,(cairo_matrix_t
*) matrix
.GetNativeMatrix());
1109 void wxCairoContext::PushState()
1111 cairo_save(m_context
);
1114 void wxCairoContext::PopState()
1116 cairo_restore(m_context
);
1119 void wxCairoContext::DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1122 Bitmap* image = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE());
1123 m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ;
1128 void wxCairoContext::DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1131 Bitmap* image = Bitmap::FromHICON((HICON)icon.GetHICON());
1132 m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ;
1138 void wxCairoContext::DrawText( const wxString
&str
, wxDouble x
, wxDouble y
)
1140 if ( m_font
.IsNull() || str
.IsEmpty())
1142 cairo_move_to(m_context
,x
,y
);
1143 const wxWX2MBbuf
buf(str
.mb_str(wxConvUTF8
));
1144 ((wxCairoFontData
*)m_font
.GetRefData())->Apply(this);
1145 cairo_show_text(m_context
,buf
);
1148 void wxCairoContext::GetTextExtent( const wxString
&str
, wxDouble
*width
, wxDouble
*height
,
1149 wxDouble
*descent
, wxDouble
*externalLeading
) const
1154 void wxCairoContext::GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const
1157 widths
.Add(0, text
.length());
1165 void * wxCairoContext::GetNativeContext()
1170 //-----------------------------------------------------------------------------
1171 // wxCairoRenderer declaration
1172 //-----------------------------------------------------------------------------
1174 class WXDLLIMPEXP_CORE wxCairoRenderer
: public wxGraphicsRenderer
1177 wxCairoRenderer() {}
1179 virtual ~wxCairoRenderer() {}
1183 virtual wxGraphicsContext
* CreateContext( const wxWindowDC
& dc
);
1186 virtual wxGraphicsContext
* CreateContext( const wxMemoryDC
& dc
);
1189 virtual wxGraphicsContext
* CreateContextFromNativeContext( void * context
);
1191 virtual wxGraphicsContext
* CreateContextFromNativeWindow( void * window
);
1193 virtual wxGraphicsContext
* CreateContext( wxWindow
* window
);
1195 virtual wxGraphicsContext
* CreateMeasuringContext();
1199 virtual wxGraphicsPath
CreatePath();
1203 virtual wxGraphicsMatrix
CreateMatrix( wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
1204 wxDouble tx
=0.0, wxDouble ty
=0.0);
1207 virtual wxGraphicsPen
CreatePen(const wxPen
& pen
) ;
1209 virtual wxGraphicsBrush
CreateBrush(const wxBrush
& brush
) ;
1211 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
1212 virtual wxGraphicsBrush
CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
1213 const wxColour
&c1
, const wxColour
&c2
) ;
1215 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
1216 // with radius r and color cColor
1217 virtual wxGraphicsBrush
CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
1218 const wxColour
&oColor
, const wxColour
&cColor
) ;
1221 virtual wxGraphicsFont
CreateFont( const wxFont
&font
, const wxColour
&col
= *wxBLACK
) ;
1224 DECLARE_DYNAMIC_CLASS_NO_COPY(wxCairoRenderer
)
1227 //-----------------------------------------------------------------------------
1228 // wxCairoRenderer implementation
1229 //-----------------------------------------------------------------------------
1231 IMPLEMENT_DYNAMIC_CLASS(wxCairoRenderer
,wxGraphicsRenderer
)
1233 static wxCairoRenderer gs_cairoGraphicsRenderer
;
1236 wxGraphicsRenderer
* wxGraphicsRenderer::GetDefaultRenderer()
1238 return &gs_cairoGraphicsRenderer
;
1242 wxGraphicsContext
* wxCairoRenderer::CreateContext( const wxWindowDC
& dc
)
1244 return new wxCairoContext(this,dc
);
1248 wxGraphicsContext
* wxCairoRenderer::CreateContext( const wxMemoryDC
& dc
)
1254 wxGraphicsContext
* wxCairoRenderer::CreateContextFromNativeContext( void * context
)
1256 return new wxCairoContext(this,(cairo_t
*)context
);
1260 wxGraphicsContext
* wxCairoRenderer::CreateContextFromNativeWindow( void * window
)
1263 return new wxCairoContext(this,(GdkDrawable
*)window
);
1269 wxGraphicsContext
* wxCairoRenderer::CreateMeasuringContext()
1275 wxGraphicsContext
* wxCairoRenderer::CreateContext( wxWindow
* window
)
1277 return new wxCairoContext(this, window
);
1282 wxGraphicsPath
wxCairoRenderer::CreatePath()
1284 wxGraphicsPath path
;
1285 path
.SetRefData( new wxCairoPathData(this) );
1292 wxGraphicsMatrix
wxCairoRenderer::CreateMatrix( wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
1293 wxDouble tx
, wxDouble ty
)
1297 wxCairoMatrixData
* data
= new wxCairoMatrixData( this );
1298 data
->Set( a
,b
,c
,d
,tx
,ty
) ;
1303 wxGraphicsPen
wxCairoRenderer::CreatePen(const wxPen
& pen
)
1305 if ( !pen
.Ok() || pen
.GetStyle() == wxTRANSPARENT
)
1306 return wxNullGraphicsPen
;
1310 p
.SetRefData(new wxCairoPenData( this, pen
));
1315 wxGraphicsBrush
wxCairoRenderer::CreateBrush(const wxBrush
& brush
)
1317 if ( !brush
.Ok() || brush
.GetStyle() == wxTRANSPARENT
)
1318 return wxNullGraphicsBrush
;
1322 p
.SetRefData(new wxCairoBrushData( this, brush
));
1327 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
1328 wxGraphicsBrush
wxCairoRenderer::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
1329 const wxColour
&c1
, const wxColour
&c2
)
1332 wxCairoBrushData
* d
= new wxCairoBrushData( this );
1333 d
->CreateLinearGradientBrush(x1
, y1
, x2
, y2
, c1
, c2
);
1338 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
1339 // with radius r and color cColor
1340 wxGraphicsBrush
wxCairoRenderer::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
1341 const wxColour
&oColor
, const wxColour
&cColor
)
1344 wxCairoBrushData
* d
= new wxCairoBrushData( this );
1345 d
->CreateRadialGradientBrush(xo
,yo
,xc
,yc
,radius
,oColor
,cColor
);
1351 wxGraphicsFont
wxCairoRenderer::CreateFont( const wxFont
&font
, const wxColour
&col
)
1356 p
.SetRefData(new wxCairoFontData( this , font
, col
));
1360 return wxNullGraphicsFont
;
1363 #endif // wxUSE_GRAPHICS_CONTEXT