]> git.saurik.com Git - wxWidgets.git/blame - src/generic/graphicc.cpp
Fixes #10443: wxListCtrl::MoveToItem
[wxWidgets.git] / src / generic / graphicc.cpp
CommitLineData
184fc6c8
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/generic/graphicc.cpp
3// Purpose: cairo device context class
4// Author: Stefan Csomor
5// Modified by:
e0876d73 6// Created: 2006-10-03
184fc6c8 7// RCS-ID: $Id$
e0876d73 8// Copyright: (c) 2006 Stefan Csomor
184fc6c8
SC
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
184fc6c8 14#ifdef __BORLANDC__
7f0d0111 15 #pragma hdrstop
184fc6c8
SC
16#endif
17
82a234fb
PC
18#if wxUSE_GRAPHICS_CONTEXT
19
184fc6c8 20#ifndef WX_PRECOMP
7f0d0111
VZ
21 #include "wx/bitmap.h"
22 #include "wx/icon.h"
23
24 #include "wx/dc.h"
25 #include "wx/dcclient.h"
26 #include "wx/dcmemory.h"
27 #include "wx/dcprint.h"
184fc6c8
SC
28#endif
29
2f94ab40 30#include "wx/private/graphics.h"
d9485f89 31#include "wx/rawbmp.h"
184fc6c8 32
184fc6c8
SC
33using namespace std;
34
35//-----------------------------------------------------------------------------
36// constants
37//-----------------------------------------------------------------------------
38
39const double RAD2DEG = 180.0 / M_PI;
40
41//-----------------------------------------------------------------------------
42// Local functions
43//-----------------------------------------------------------------------------
44
45static inline double dmin(double a, double b)
46{
47 return a < b ? a : b;
48}
49static inline double dmax(double a, double b)
50{
51 return a > b ? a : b;
52}
53
54static inline double DegToRad(double deg)
55{
56 return (deg * M_PI) / 180.0;
57}
58static inline double RadToDeg(double deg)
59{
60 return (deg * 180.0) / M_PI;
61}
62
63//-----------------------------------------------------------------------------
64// device context implementation
65//
66// more and more of the dc functionality should be implemented by calling
67// the appropricate wxCairoContext, but we will have to do that step by step
68// also coordinate conversions should be moved to native matrix ops
69//-----------------------------------------------------------------------------
70
71// we always stock two context states, one at entry, to be able to preserve the
72// state we were called with, the other one after changing to HI Graphics orientation
73// (this one is used for getting back clippings etc)
74
75//-----------------------------------------------------------------------------
76// wxGraphicsPath implementation
77//-----------------------------------------------------------------------------
78
79// TODO remove this dependency (gdiplus needs the macros)
80
81#ifndef max
82#define max(a,b) (((a) > (b)) ? (a) : (b))
83#endif
84
85#ifndef min
86#define min(a,b) (((a) < (b)) ? (a) : (b))
87#endif
88
89#include <cairo.h>
00bd8e72 90#ifdef __WXGTK__
184fc6c8 91#include <gtk/gtk.h>
84f67b11 92#include "wx/fontutil.h"
888dde65 93#include "wx/gtk/dc.h"
00bd8e72 94#endif
184fc6c8 95
e7f9f819
SC
96#ifdef __WXMSW__
97#include <cairo-win32.h>
98#endif
99
100#ifdef __WXMAC__
33ddeaba 101#include "wx/osx/private.h"
e7f9f819
SC
102#include <cairo-quartz.h>
103#include <cairo-atsui.h>
104#endif
105
0db8a70e 106class WXDLLIMPEXP_CORE wxCairoPathData : public wxGraphicsPathData
184fc6c8 107{
184fc6c8 108public :
0db8a70e
RD
109 wxCairoPathData(wxGraphicsRenderer* renderer, cairo_t* path = NULL);
110 ~wxCairoPathData();
184fc6c8 111
0db8a70e 112 virtual wxGraphicsObjectRefData *Clone() const;
184fc6c8
SC
113
114 //
115 // These are the path primitives from which everything else can be constructed
116 //
117
118 // begins a new subpath at (x,y)
119 virtual void MoveToPoint( wxDouble x, wxDouble y );
120
121 // adds a straight line from the current point to (x,y)
122 virtual void AddLineToPoint( wxDouble x, wxDouble y );
123
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 );
126
127
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 ) ;
130
131 // gets the last point of the current path, (0,0) if not yet set
0db8a70e 132 virtual void GetCurrentPoint( wxDouble* x, wxDouble* y) const;
184fc6c8 133
00bd8e72 134 // adds another path
0db8a70e 135 virtual void AddPath( const wxGraphicsPathData* path );
00bd8e72 136
184fc6c8
SC
137 // closes the current sub-path
138 virtual void CloseSubpath();
139
140 //
141 // These are convenience functions which - if not available natively will be assembled
142 // using the primitives from above
143 //
144
145 /*
146
49ad157e 147 // appends a rectangle as a new closed subpath
184fc6c8
SC
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 ) ;
151
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 ) ;
154 */
155
cd5adaa6
RD
156 // returns the native path
157 virtual void * GetNativePath() const ;
158
159 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
0db8a70e 160 virtual void UnGetNativePath(void *p) const;
f540e5bd 161
00bd8e72 162 // transforms each point of this path by the matrix
0db8a70e 163 virtual void Transform( const wxGraphicsMatrixData* matrix ) ;
00bd8e72
SC
164
165 // gets the bounding box enclosing all points (possibly including control points)
0db8a70e 166 virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const;
00bd8e72 167
94a007ec 168 virtual bool Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle = wxWINDING_RULE) const;
00bd8e72 169
184fc6c8
SC
170private :
171 cairo_t* m_pathContext;
172};
173
0db8a70e 174class WXDLLIMPEXP_CORE wxCairoMatrixData : public wxGraphicsMatrixData
184fc6c8 175{
00bd8e72 176public :
0db8a70e
RD
177 wxCairoMatrixData(wxGraphicsRenderer* renderer, const cairo_matrix_t* matrix = NULL ) ;
178 virtual ~wxCairoMatrixData() ;
184fc6c8 179
0db8a70e 180 virtual wxGraphicsObjectRefData *Clone() const ;
184fc6c8 181
00bd8e72 182 // concatenates the matrix
0db8a70e 183 virtual void Concat( const wxGraphicsMatrixData *t );
184fc6c8 184
00bd8e72 185 // sets the matrix to the respective values
49ad157e 186 virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
00bd8e72 187 wxDouble tx=0.0, wxDouble ty=0.0);
184fc6c8 188
248802d0
RD
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;
49ad157e 192
00bd8e72
SC
193 // makes this the inverse matrix
194 virtual void Invert();
184fc6c8 195
00bd8e72 196 // returns true if the elements of the transformation matrix are equal ?
0db8a70e 197 virtual bool IsEqual( const wxGraphicsMatrixData* t) const ;
184fc6c8 198
00bd8e72 199 // return true if this is the identity matrix
0db8a70e 200 virtual bool IsIdentity() const;
184fc6c8 201
00bd8e72
SC
202 //
203 // transformation
204 //
184fc6c8 205
00bd8e72
SC
206 // add the translation to this matrix
207 virtual void Translate( wxDouble dx , wxDouble dy );
208
209 // add the scale to this matrix
210 virtual void Scale( wxDouble xScale , wxDouble yScale );
211
212 // add the rotation to this matrix (radians)
49ad157e 213 virtual void Rotate( wxDouble angle );
00bd8e72
SC
214
215 //
216 // apply the transforms
217 //
218
219 // applies that matrix to the point
0db8a70e 220 virtual void TransformPoint( wxDouble *x, wxDouble *y ) const;
00bd8e72
SC
221
222 // applies the matrix except for translations
0db8a70e 223 virtual void TransformDistance( wxDouble *dx, wxDouble *dy ) const;
00bd8e72
SC
224
225 // returns the native representation
226 virtual void * GetNativeMatrix() const;
227private:
228 cairo_matrix_t m_matrix ;
00bd8e72
SC
229} ;
230
87752530 231class WXDLLIMPEXP_CORE wxCairoPenData : public wxGraphicsObjectRefData
184fc6c8 232{
00bd8e72 233public:
87752530
SC
234 wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen );
235 ~wxCairoPenData();
00bd8e72
SC
236
237 void Init();
238
239 virtual void Apply( wxGraphicsContext* context );
240 virtual wxDouble GetWidth() { return m_width; }
241
242private :
243 double m_width;
49ad157e 244
00bd8e72
SC
245 double m_red;
246 double m_green;
247 double m_blue;
248 double m_alpha;
49ad157e 249
00bd8e72
SC
250 cairo_line_cap_t m_cap;
251 cairo_line_join_t m_join;
252
253 int m_count;
254 const double *m_lengths;
255 double *m_userLengths;
184fc6c8 256
00bd8e72 257 wxPen m_pen;
00bd8e72
SC
258};
259
87752530 260class WXDLLIMPEXP_CORE wxCairoBrushData : public wxGraphicsObjectRefData
184fc6c8 261{
00bd8e72 262public:
87752530
SC
263 wxCairoBrushData( wxGraphicsRenderer* renderer );
264 wxCairoBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush );
265 ~wxCairoBrushData ();
00bd8e72
SC
266
267 virtual void Apply( wxGraphicsContext* context );
49ad157e 268 void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
00bd8e72
SC
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 );
272
273protected:
274 virtual void Init();
275
276private :
277 double m_red;
278 double m_green;
279 double m_blue;
280 double m_alpha;
281
282 cairo_pattern_t* m_brushPattern;
00bd8e72
SC
283};
284
87752530 285class wxCairoFontData : public wxGraphicsObjectRefData
184fc6c8 286{
00bd8e72 287public:
87752530
SC
288 wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
289 ~wxCairoFontData();
00bd8e72
SC
290
291 virtual void Apply( wxGraphicsContext* context );
84f67b11
SC
292#ifdef __WXGTK__
293 const PangoFontDescription* GetFont() const { return m_font; }
0d19936d 294 bool GetUnderlined() const { return m_underlined; }
84f67b11 295#endif
00bd8e72 296private :
00bd8e72 297 double m_size;
0d19936d 298 bool m_underlined;
00bd8e72
SC
299 double m_red;
300 double m_green;
301 double m_blue;
302 double m_alpha;
84f67b11 303#ifdef __WXMAC__
e7f9f819 304 cairo_font_face_t *m_font;
84f67b11
SC
305#elif defined(__WXGTK__)
306 PangoFontDescription* m_font;
307#else
308 wxCharBuffer m_fontName;
309 cairo_font_slant_t m_slant;
310 cairo_font_weight_t m_weight;
311#endif
00bd8e72 312};
184fc6c8 313
00bd8e72 314class WXDLLIMPEXP_CORE wxCairoContext : public wxGraphicsContext
184fc6c8 315{
184fc6c8 316public:
00bd8e72 317 wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC& dc );
888dde65 318 wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& dc );
c9008abe 319 wxCairoContext( wxGraphicsRenderer* renderer, const wxPrinterDC& dc );
00bd8e72
SC
320#ifdef __WXGTK__
321 wxCairoContext( wxGraphicsRenderer* renderer, GdkDrawable *drawable );
322#endif
323 wxCairoContext( wxGraphicsRenderer* renderer, cairo_t *context );
324 wxCairoContext( wxGraphicsRenderer* renderer, wxWindow *window);
184fc6c8
SC
325 wxCairoContext();
326 virtual ~wxCairoContext();
327
e7f9f819 328 virtual bool ShouldOffset() const
49ad157e 329 {
e7f9f819
SC
330 int penwidth = 0 ;
331 if ( !m_pen.IsNull() )
332 {
333 penwidth = (int)((wxCairoPenData*)m_pen.GetRefData())->GetWidth();
334 if ( penwidth == 0 )
335 penwidth = 1;
336 }
337 return ( penwidth % 2 ) == 1;
338 }
339
184fc6c8 340 virtual void Clip( const wxRegion &region );
539e2795
SC
341
342 // clips drawings to the rect
343 virtual void Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
539e2795 344
cd5adaa6
RD
345 // resets the clipping to original extent
346 virtual void ResetClip();
347
348 virtual void * GetNativeContext();
349
89efaf2b 350 virtual bool SetLogicalFunction( wxRasterOperationMode function );
49ad157e 351
0db8a70e 352 virtual void StrokePath( const wxGraphicsPath& p );
94a007ec 353 virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxWINDING_RULE );
184fc6c8 354
184fc6c8
SC
355 virtual void Translate( wxDouble dx , wxDouble dy );
356 virtual void Scale( wxDouble xScale , wxDouble yScale );
357 virtual void Rotate( wxDouble angle );
358
00bd8e72 359 // concatenates this transform with the current transform of this context
0db8a70e 360 virtual void ConcatTransform( const wxGraphicsMatrix& matrix );
00bd8e72
SC
361
362 // sets the transform of this context
0db8a70e 363 virtual void SetTransform( const wxGraphicsMatrix& matrix );
00bd8e72
SC
364
365 // gets the matrix of this context
0db8a70e 366 virtual wxGraphicsMatrix GetTransform() const;
00bd8e72 367
184fc6c8
SC
368 virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
369 virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
370 virtual void PushState();
371 virtual void PopState();
372
184fc6c8
SC
373 virtual void GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
374 wxDouble *descent, wxDouble *externalLeading ) const;
375 virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
376
377private:
e7f9f819 378 void Init(cairo_t *context);
49ad157e 379
0b7dce54
VZ
380 virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y );
381
184fc6c8 382 cairo_t* m_context;
0b7dce54
VZ
383
384 DECLARE_NO_COPY_CLASS(wxCairoContext)
184fc6c8
SC
385};
386
184fc6c8 387//-----------------------------------------------------------------------------
87752530 388// wxCairoPenData implementation
184fc6c8
SC
389//-----------------------------------------------------------------------------
390
87752530 391wxCairoPenData::~wxCairoPenData()
539e2795 392{
00bd8e72 393 delete[] m_userLengths;
539e2795 394}
cd5adaa6 395
87752530 396void wxCairoPenData::Init()
539e2795 397{
00bd8e72
SC
398 m_lengths = NULL;
399 m_userLengths = NULL;
400 m_width = 0;
401 m_count = 0;
539e2795
SC
402}
403
87752530
SC
404wxCairoPenData::wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen )
405: wxGraphicsObjectRefData(renderer)
49ad157e 406{
00bd8e72 407 Init();
7f8bd9fc
RD
408 m_pen = pen;
409 m_width = m_pen.GetWidth();
00bd8e72
SC
410 if (m_width <= 0.0)
411 m_width = 0.1;
539e2795 412
00bd8e72 413 m_red = m_pen.GetColour().Red()/255.0;
49ad157e 414 m_green = m_pen.GetColour().Green()/255.0;
00bd8e72
SC
415 m_blue = m_pen.GetColour().Blue()/255.0;
416 m_alpha = m_pen.GetColour().Alpha()/255.0;
184fc6c8 417
184fc6c8
SC
418 switch ( m_pen.GetCap() )
419 {
420 case wxCAP_ROUND :
00bd8e72 421 m_cap = CAIRO_LINE_CAP_ROUND;
184fc6c8
SC
422 break;
423
424 case wxCAP_PROJECTING :
00bd8e72 425 m_cap = CAIRO_LINE_CAP_SQUARE;
184fc6c8
SC
426 break;
427
428 case wxCAP_BUTT :
00bd8e72 429 m_cap = CAIRO_LINE_CAP_BUTT;
184fc6c8
SC
430 break;
431
432 default :
00bd8e72 433 m_cap = CAIRO_LINE_CAP_BUTT;
184fc6c8
SC
434 break;
435 }
184fc6c8 436
184fc6c8
SC
437 switch ( m_pen.GetJoin() )
438 {
439 case wxJOIN_BEVEL :
00bd8e72 440 m_join = CAIRO_LINE_JOIN_BEVEL;
184fc6c8
SC
441 break;
442
443 case wxJOIN_MITER :
00bd8e72 444 m_join = CAIRO_LINE_JOIN_MITER;
184fc6c8
SC
445 break;
446
447 case wxJOIN_ROUND :
00bd8e72 448 m_join = CAIRO_LINE_JOIN_ROUND;
184fc6c8
SC
449 break;
450
451 default :
00bd8e72 452 m_join = CAIRO_LINE_JOIN_MITER;
184fc6c8
SC
453 break;
454 }
184fc6c8 455
00bd8e72 456 const double dashUnit = m_width < 1.0 ? 1.0 : m_width;
184fc6c8 457 const double dotted[] =
00bd8e72
SC
458 {
459 dashUnit , dashUnit + 2.0
460 };
461 static const double short_dashed[] =
462 {
463 9.0 , 6.0
464 };
465 static const double dashed[] =
466 {
467 19.0 , 9.0
468 };
469 static const double dotted_dashed[] =
470 {
471 9.0 , 6.0 , 3.0 , 3.0
472 };
184fc6c8
SC
473
474 switch ( m_pen.GetStyle() )
475 {
fb040094 476 case wxPENSTYLE_SOLID :
184fc6c8
SC
477 break;
478
fb040094 479 case wxPENSTYLE_DOT :
00bd8e72
SC
480 m_count = WXSIZEOF(dotted);
481 m_userLengths = new double[ m_count ] ;
482 memcpy( m_userLengths, dotted, sizeof(dotted) );
483 m_lengths = m_userLengths;
184fc6c8
SC
484 break;
485
fb040094 486 case wxPENSTYLE_LONG_DASH :
84f67b11 487 m_lengths = dashed ;
00bd8e72 488 m_count = WXSIZEOF(dashed);
184fc6c8
SC
489 break;
490
fb040094 491 case wxPENSTYLE_SHORT_DASH :
84f67b11 492 m_lengths = short_dashed ;
00bd8e72 493 m_count = WXSIZEOF(short_dashed);
184fc6c8
SC
494 break;
495
fb040094 496 case wxPENSTYLE_DOT_DASH :
84f67b11 497 m_lengths = dotted_dashed ;
00bd8e72 498 m_count = WXSIZEOF(dotted_dashed);
184fc6c8
SC
499 break;
500
fb040094 501 case wxPENSTYLE_USER_DASH :
184fc6c8
SC
502 {
503 wxDash *wxdashes ;
00bd8e72
SC
504 m_count = m_pen.GetDashes( &wxdashes ) ;
505 if ((wxdashes != NULL) && (m_count > 0))
184fc6c8 506 {
00bd8e72
SC
507 m_userLengths = new double[m_count] ;
508 for ( int i = 0 ; i < m_count ; ++i )
184fc6c8 509 {
00bd8e72 510 m_userLengths[i] = wxdashes[i] * dashUnit ;
184fc6c8 511
00bd8e72
SC
512 if ( i % 2 == 1 && m_userLengths[i] < dashUnit + 2.0 )
513 m_userLengths[i] = dashUnit + 2.0 ;
514 else if ( i % 2 == 0 && m_userLengths[i] < dashUnit )
515 m_userLengths[i] = dashUnit ;
184fc6c8
SC
516 }
517 }
00bd8e72 518 m_lengths = m_userLengths ;
184fc6c8
SC
519 }
520 break;
fb040094 521 case wxPENSTYLE_STIPPLE :
184fc6c8
SC
522 {
523 /*
00bd8e72
SC
524 wxBitmap* bmp = pen.GetStipple();
525 if ( bmp && bmp->Ok() )
526 {
527 wxDELETE( m_penImage );
528 wxDELETE( m_penBrush );
529 m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE());
530 m_penBrush = new TextureBrush(m_penImage);
531 m_pen->SetBrush( m_penBrush );
532 }
184fc6c8
SC
533 */
534 }
535 break;
536 default :
89efaf2b 537 if ( m_pen.GetStyle() >= wxPENSTYLE_FIRST_HATCH
fb040094 538 && m_pen.GetStyle() <= wxPENSTYLE_LAST_HATCH )
184fc6c8
SC
539 {
540 /*
00bd8e72
SC
541 wxDELETE( m_penBrush );
542 HatchStyle style = HatchStyleHorizontal;
543 switch( pen.GetStyle() )
544 {
fb040094 545 case wxPENSTYLE_BDIAGONAL_HATCH :
00bd8e72
SC
546 style = HatchStyleBackwardDiagonal;
547 break ;
fb040094 548 case wxPENSTYLE_CROSSDIAG_HATCH :
00bd8e72
SC
549 style = HatchStyleDiagonalCross;
550 break ;
fb040094 551 case wxPENSTYLE_FDIAGONAL_HATCH :
00bd8e72
SC
552 style = HatchStyleForwardDiagonal;
553 break ;
fb040094 554 case wxPENSTYLE_CROSS_HATCH :
00bd8e72
SC
555 style = HatchStyleCross;
556 break ;
fb040094 557 case wxPENSTYLE_HORIZONTAL_HATCH :
00bd8e72
SC
558 style = HatchStyleHorizontal;
559 break ;
fb040094 560 case wxPENSTYLE_VERTICAL_HATCH :
00bd8e72
SC
561 style = HatchStyleVertical;
562 break ;
563
564 }
565 m_penBrush = new HatchBrush(style,Color( pen.GetColour().Alpha() , pen.GetColour().Red() ,
566 pen.GetColour().Green() , pen.GetColour().Blue() ), Color.Transparent );
567 m_pen->SetBrush( m_penBrush )
184fc6c8
SC
568 */
569 }
570 break;
571 }
00bd8e72 572}
184fc6c8 573
87752530 574void wxCairoPenData::Apply( wxGraphicsContext* context )
00bd8e72
SC
575{
576 cairo_t * ctext = (cairo_t*) context->GetNativeContext();
577 cairo_set_line_width(ctext,m_width);
578 cairo_set_source_rgba(ctext,m_red,m_green, m_blue,m_alpha);
579 cairo_set_line_cap(ctext,m_cap);
580 cairo_set_line_join(ctext,m_join);
581 cairo_set_dash(ctext,(double*)m_lengths,m_count,0.0);
184fc6c8
SC
582}
583
00bd8e72 584//-----------------------------------------------------------------------------
87752530 585// wxCairoBrushData implementation
00bd8e72
SC
586//-----------------------------------------------------------------------------
587
7f8bd9fc
RD
588wxCairoBrushData::wxCairoBrushData( wxGraphicsRenderer* renderer )
589 : wxGraphicsObjectRefData( renderer )
00bd8e72
SC
590{
591 Init();
592}
184fc6c8 593
87752530 594wxCairoBrushData::wxCairoBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush )
7f8bd9fc 595 : wxGraphicsObjectRefData(renderer)
00bd8e72 596{
7f8bd9fc 597 Init();
49ad157e 598
00bd8e72 599 m_red = brush.GetColour().Red()/255.0;
49ad157e 600 m_green = brush.GetColour().Green()/255.0;
00bd8e72
SC
601 m_blue = brush.GetColour().Blue()/255.0;
602 m_alpha = brush.GetColour().Alpha()/255.0;
603 /*
fb040094 604 if ( brush.GetStyle() == wxBRUSHSTYLE_SOLID)
00bd8e72
SC
605 {
606 m_brush = new SolidBrush( Color( brush.GetColour().Alpha() , brush.GetColour().Red() ,
607 brush.GetColour().Green() , brush.GetColour().Blue() ) );
608 }
609 else if ( brush.IsHatch() )
610 {
611 HatchStyle style = HatchStyleHorizontal;
612 switch( brush.GetStyle() )
613 {
fb040094 614 case wxBRUSHSTYLE_BDIAGONAL_HATCH :
00bd8e72
SC
615 style = HatchStyleBackwardDiagonal;
616 break ;
fb040094 617 case wxBRUSHSTYLE_CROSSDIAG_HATCH :
00bd8e72
SC
618 style = HatchStyleDiagonalCross;
619 break ;
fb040094 620 case wxBRUSHSTYLE_FDIAGONAL_HATCH :
00bd8e72
SC
621 style = HatchStyleForwardDiagonal;
622 break ;
fb040094 623 case wxBRUSHSTYLE_CROSS_HATCH :
00bd8e72
SC
624 style = HatchStyleCross;
625 break ;
fb040094 626 case wxBRUSHSTYLE_HORIZONTAL_HATCH :
00bd8e72
SC
627 style = HatchStyleHorizontal;
628 break ;
fb040094 629 case wxBRUSHSTYLE_VERTICAL_HATCH :
00bd8e72
SC
630 style = HatchStyleVertical;
631 break ;
632
633 }
634 m_brush = new HatchBrush(style,Color( brush.GetColour().Alpha() , brush.GetColour().Red() ,
635 brush.GetColour().Green() , brush.GetColour().Blue() ), Color.Transparent );
636 }
49ad157e 637 else
00bd8e72
SC
638 {
639 wxBitmap* bmp = brush.GetStipple();
640 if ( bmp && bmp->Ok() )
641 {
642 wxDELETE( m_brushImage );
643 m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE());
644 m_brush = new TextureBrush(m_brushImage);
645 }
184fc6c8 646 }
00bd8e72 647 */
184fc6c8
SC
648}
649
87752530 650wxCairoBrushData::~wxCairoBrushData ()
184fc6c8 651{
00bd8e72
SC
652 if (m_brushPattern)
653 cairo_pattern_destroy(m_brushPattern);
184fc6c8
SC
654}
655
87752530 656void wxCairoBrushData::Apply( wxGraphicsContext* context )
184fc6c8 657{
00bd8e72
SC
658 cairo_t * ctext = (cairo_t*) context->GetNativeContext();
659 if ( m_brushPattern )
660 {
661 cairo_set_source(ctext,m_brushPattern);
662 }
663 else
664 {
665 cairo_set_source_rgba(ctext,m_red,m_green, m_blue,m_alpha);
666 }
184fc6c8
SC
667}
668
49ad157e 669void wxCairoBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
00bd8e72 670 const wxColour&c1, const wxColour&c2 )
184fc6c8 671{
00bd8e72
SC
672 m_brushPattern = cairo_pattern_create_linear(x1,y1,x2,y2);
673 cairo_pattern_add_color_stop_rgba(m_brushPattern,0.0,c1.Red()/255.0,
674 c1.Green()/255.0, c1.Blue()/255.0,c1.Alpha()/255.0);
675 cairo_pattern_add_color_stop_rgba(m_brushPattern,1.0,c2.Red()/255.0,
676 c2.Green()/255.0, c2.Blue()/255.0,c2.Alpha()/255.0);
677 wxASSERT_MSG(cairo_pattern_status(m_brushPattern) == CAIRO_STATUS_SUCCESS, wxT("Couldn't create cairo pattern"));
184fc6c8
SC
678}
679
87752530 680void wxCairoBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
00bd8e72 681 const wxColour &oColor, const wxColour &cColor )
184fc6c8 682{
00bd8e72
SC
683 m_brushPattern = cairo_pattern_create_radial(xo,yo,0.0,xc,yc,radius);
684 cairo_pattern_add_color_stop_rgba(m_brushPattern,0.0,oColor.Red()/255.0,
685 oColor.Green()/255.0, oColor.Blue()/255.0,oColor.Alpha()/255.0);
686 cairo_pattern_add_color_stop_rgba(m_brushPattern,1.0,cColor.Red()/255.0,
687 cColor.Green()/255.0, cColor.Blue()/255.0,cColor.Alpha()/255.0);
688 wxASSERT_MSG(cairo_pattern_status(m_brushPattern) == CAIRO_STATUS_SUCCESS, wxT("Couldn't create cairo pattern"));
184fc6c8
SC
689}
690
87752530 691void wxCairoBrushData::Init()
184fc6c8 692{
00bd8e72 693 m_brushPattern = NULL;
184fc6c8
SC
694}
695
00bd8e72 696//-----------------------------------------------------------------------------
87752530 697// wxCairoFontData implementation
00bd8e72
SC
698//-----------------------------------------------------------------------------
699
49ad157e 700wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &font,
87752530 701 const wxColour& col ) : wxGraphicsObjectRefData(renderer)
184fc6c8 702{
00bd8e72 703 m_red = col.Red()/255.0;
49ad157e 704 m_green = col.Green()/255.0;
00bd8e72
SC
705 m_blue = col.Blue()/255.0;
706 m_alpha = col.Alpha()/255.0;
00bd8e72 707 m_size = font.GetPointSize();
0d19936d 708 m_underlined = font.GetUnderlined();
84f67b11
SC
709
710#ifdef __WXMAC__
711 m_font = cairo_atsui_font_face_create_for_atsu_font_id( font.MacGetATSUFontID() );
712#elif defined(__WXGTK__)
713 m_font = pango_font_description_copy( font.GetNativeFontInfo()->description );
714#else
00bd8e72
SC
715 m_fontName = font.GetFaceName().mb_str(wxConvUTF8);
716 m_slant = font.GetStyle() == wxFONTSTYLE_ITALIC ? CAIRO_FONT_SLANT_ITALIC:CAIRO_FONT_SLANT_NORMAL;
717 m_weight = font.GetWeight() == wxFONTWEIGHT_BOLD ? CAIRO_FONT_WEIGHT_BOLD:CAIRO_FONT_WEIGHT_NORMAL;
e7f9f819 718#endif
184fc6c8
SC
719}
720
87752530 721wxCairoFontData::~wxCairoFontData()
184fc6c8 722{
84f67b11 723#ifdef __WXMAC__
e7f9f819 724 cairo_font_face_destroy( m_font );
84f67b11
SC
725#elif defined(__WXGTK__)
726 pango_font_description_free( m_font );
727#else
728#endif
00bd8e72 729}
184fc6c8 730
87752530 731void wxCairoFontData::Apply( wxGraphicsContext* context )
00bd8e72
SC
732{
733 cairo_t * ctext = (cairo_t*) context->GetNativeContext();
734 cairo_set_source_rgba(ctext,m_red,m_green, m_blue,m_alpha);
84f67b11
SC
735#ifdef __WXGTK__
736 // the rest is done using Pango layouts
737#elif defined(__WXMAC__)
738 cairo_set_font_face(ctext, m_font);
3e700936 739 cairo_set_font_size(ctext, m_size );
84f67b11
SC
740#else
741 cairo_select_font_face(ctext, m_fontName, m_slant, m_weights );
742 cairo_set_font_size(ctext, m_size );
e7f9f819 743#endif
00bd8e72
SC
744}
745
746//-----------------------------------------------------------------------------
0db8a70e 747// wxCairoPathData implementation
00bd8e72
SC
748//-----------------------------------------------------------------------------
749
0db8a70e
RD
750wxCairoPathData::wxCairoPathData( wxGraphicsRenderer* renderer, cairo_t* pathcontext)
751 : wxGraphicsPathData(renderer)
184fc6c8 752{
00bd8e72 753 if (pathcontext)
184fc6c8 754 {
00bd8e72
SC
755 m_pathContext = pathcontext;
756 }
757 else
758 {
759 cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,1,1);
760 m_pathContext = cairo_create(surface);
761 cairo_surface_destroy (surface);
184fc6c8 762 }
00bd8e72 763}
184fc6c8 764
0db8a70e 765wxCairoPathData::~wxCairoPathData()
00bd8e72
SC
766{
767 cairo_destroy(m_pathContext);
184fc6c8
SC
768}
769
0db8a70e 770wxGraphicsObjectRefData *wxCairoPathData::Clone() const
184fc6c8 771{
00bd8e72
SC
772 cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,1,1);
773 cairo_t* pathcontext = cairo_create(surface);
774 cairo_surface_destroy (surface);
775
776 cairo_path_t* path = cairo_copy_path(m_pathContext);
777 cairo_append_path(pathcontext, path);
778 cairo_path_destroy(path);
0db8a70e 779 return new wxCairoPathData( GetRenderer() ,pathcontext);
00bd8e72
SC
780}
781
782
0db8a70e 783void* wxCairoPathData::GetNativePath() const
00bd8e72
SC
784{
785 return cairo_copy_path(m_pathContext) ;
786}
787
0db8a70e 788void wxCairoPathData::UnGetNativePath(void *p) const
00bd8e72
SC
789{
790 cairo_path_destroy((cairo_path_t*)p);
791}
792
793//
794// The Primitives
795//
796
0db8a70e 797void wxCairoPathData::MoveToPoint( wxDouble x , wxDouble y )
00bd8e72
SC
798{
799 cairo_move_to(m_pathContext,x,y);
800}
801
0db8a70e 802void wxCairoPathData::AddLineToPoint( wxDouble x , wxDouble y )
00bd8e72
SC
803{
804 cairo_line_to(m_pathContext,x,y);
805}
806
0db8a70e 807void wxCairoPathData::AddPath( const wxGraphicsPathData* path )
6b06903d 808{
d9485f89
RD
809 cairo_path_t* p = (cairo_path_t*)path->GetNativePath();
810 cairo_append_path(m_pathContext, p);
811 UnGetNativePath(p);
6b06903d
RD
812}
813
0db8a70e 814void wxCairoPathData::CloseSubpath()
00bd8e72
SC
815{
816 cairo_close_path(m_pathContext);
817}
818
0db8a70e 819void wxCairoPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
00bd8e72
SC
820{
821 cairo_curve_to(m_pathContext,cx1,cy1,cx2,cy2,x,y);
822}
823
824// gets the last point of the current path, (0,0) if not yet set
0db8a70e 825void wxCairoPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
00bd8e72
SC
826{
827 double dx,dy;
828 cairo_get_current_point(m_pathContext,&dx,&dy);
0db8a70e
RD
829 if (x)
830 *x = dx;
831 if (y)
832 *y = dy;
00bd8e72
SC
833}
834
0db8a70e 835void wxCairoPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, double startAngle, double endAngle, bool clockwise )
00bd8e72 836{
49ad157e 837 // as clockwise means positive in our system (y pointing downwards)
00bd8e72
SC
838 // TODO make this interpretation dependent of the
839 // real device trans
840 if ( clockwise||(endAngle-startAngle)>=2*M_PI)
841 cairo_arc(m_pathContext,x,y,r,startAngle,endAngle);
842 else
843 cairo_arc_negative(m_pathContext,x,y,r,startAngle,endAngle);
844}
845
846// transforms each point of this path by the matrix
49ad157e 847void wxCairoPathData::Transform( const wxGraphicsMatrixData* matrix )
00bd8e72
SC
848{
849 // as we don't have a true path object, we have to apply the inverse
850 // matrix to the context
851 cairo_matrix_t m = *((cairo_matrix_t*) matrix->GetNativeMatrix());
852 cairo_matrix_invert( &m );
853 cairo_transform(m_pathContext,&m);
49ad157e 854}
00bd8e72
SC
855
856// gets the bounding box enclosing all points (possibly including control points)
0db8a70e 857void wxCairoPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const
00bd8e72
SC
858{
859 double x1,y1,x2,y2;
860
861 cairo_stroke_extents( m_pathContext, &x1, &y1, &x2, &y2 );
862 if ( x2 < x1 )
184fc6c8 863 {
00bd8e72
SC
864 *x = x2;
865 *w = x1-x2;
866 }
867 else
868 {
869 *x = x1;
870 *w = x2-x1;
184fc6c8 871 }
49ad157e 872
00bd8e72
SC
873 if( y2 < y1 )
874 {
875 *y = y2;
876 *h = y1-y2;
877 }
878 else
879 {
880 *y = y1;
881 *h = y2-y1;
882 }
883}
884
94a007ec 885bool wxCairoPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode WXUNUSED(fillStyle) ) const
00bd8e72 886{
0db8a70e 887 return cairo_in_stroke( m_pathContext, x, y) != 0;
00bd8e72
SC
888}
889
890//-----------------------------------------------------------------------------
0db8a70e 891// wxCairoMatrixData implementation
00bd8e72
SC
892//-----------------------------------------------------------------------------
893
0db8a70e
RD
894wxCairoMatrixData::wxCairoMatrixData(wxGraphicsRenderer* renderer, const cairo_matrix_t* matrix )
895 : wxGraphicsMatrixData(renderer)
00bd8e72
SC
896{
897 if ( matrix )
898 m_matrix = *matrix;
899}
900
49ad157e 901wxCairoMatrixData::~wxCairoMatrixData()
00bd8e72
SC
902{
903 // nothing to do
904}
905
49ad157e 906wxGraphicsObjectRefData *wxCairoMatrixData::Clone() const
00bd8e72 907{
0db8a70e 908 return new wxCairoMatrixData(GetRenderer(),&m_matrix);
00bd8e72
SC
909}
910
911// concatenates the matrix
49ad157e 912void wxCairoMatrixData::Concat( const wxGraphicsMatrixData *t )
00bd8e72 913{
49ad157e 914 cairo_matrix_multiply( &m_matrix, &m_matrix, (cairo_matrix_t*) t->GetNativeMatrix());
00bd8e72
SC
915}
916
00bd8e72 917// sets the matrix to the respective values
49ad157e
VZ
918void wxCairoMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
919 wxDouble tx, wxDouble ty)
00bd8e72
SC
920{
921 cairo_matrix_init( &m_matrix, a, b, c, d, tx, ty);
922}
923
248802d0
RD
924// gets the component valuess of the matrix
925void wxCairoMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
926 wxDouble* d, wxDouble* tx, wxDouble* ty) const
927{
928 if (a) *a = m_matrix.xx;
929 if (b) *b = m_matrix.yx;
930 if (c) *c = m_matrix.xy;
931 if (d) *d = m_matrix.yy;
932 if (tx) *tx= m_matrix.x0;
933 if (ty) *ty= m_matrix.y0;
934}
935
00bd8e72 936// makes this the inverse matrix
49ad157e 937void wxCairoMatrixData::Invert()
00bd8e72
SC
938{
939 cairo_matrix_invert( &m_matrix );
940}
941
942// returns true if the elements of the transformation matrix are equal ?
49ad157e 943bool wxCairoMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
00bd8e72
SC
944{
945 const cairo_matrix_t* tm = (cairo_matrix_t*) t->GetNativeMatrix();
49ad157e
VZ
946 return (
947 m_matrix.xx == tm->xx &&
948 m_matrix.yx == tm->yx &&
949 m_matrix.xy == tm->xy &&
950 m_matrix.yy == tm->yy &&
951 m_matrix.x0 == tm->x0 &&
00bd8e72
SC
952 m_matrix.y0 == tm->y0 ) ;
953}
954
955// return true if this is the identity matrix
0db8a70e 956bool wxCairoMatrixData::IsIdentity() const
00bd8e72
SC
957{
958 return ( m_matrix.xx == 1 && m_matrix.yy == 1 &&
959 m_matrix.yx == 0 && m_matrix.xy == 0 && m_matrix.x0 == 0 && m_matrix.y0 == 0);
960}
961
962//
963// transformation
964//
965
966// add the translation to this matrix
0db8a70e 967void wxCairoMatrixData::Translate( wxDouble dx , wxDouble dy )
00bd8e72
SC
968{
969 cairo_matrix_translate( &m_matrix, dx, dy) ;
970}
971
972// add the scale to this matrix
0db8a70e 973void wxCairoMatrixData::Scale( wxDouble xScale , wxDouble yScale )
00bd8e72
SC
974{
975 cairo_matrix_scale( &m_matrix, xScale, yScale) ;
976}
977
978// add the rotation to this matrix (radians)
49ad157e 979void wxCairoMatrixData::Rotate( wxDouble angle )
00bd8e72
SC
980{
981 cairo_matrix_rotate( &m_matrix, angle) ;
49ad157e 982}
00bd8e72
SC
983
984//
985// apply the transforms
986//
987
988// applies that matrix to the point
0db8a70e 989void wxCairoMatrixData::TransformPoint( wxDouble *x, wxDouble *y ) const
00bd8e72
SC
990{
991 double lx = *x, ly = *y ;
992 cairo_matrix_transform_point( &m_matrix, &lx, &ly);
993 *x = lx;
994 *y = ly;
995}
996
997// applies the matrix except for translations
0db8a70e 998void wxCairoMatrixData::TransformDistance( wxDouble *dx, wxDouble *dy ) const
00bd8e72
SC
999{
1000 double lx = *dx, ly = *dy ;
1001 cairo_matrix_transform_distance( &m_matrix, &lx, &ly);
1002 *dx = lx;
1003 *dy = ly;
1004}
1005
1006// returns the native representation
0db8a70e 1007void * wxCairoMatrixData::GetNativeMatrix() const
00bd8e72
SC
1008{
1009 return (void*) &m_matrix;
1010}
1011
1012//-----------------------------------------------------------------------------
1013// wxCairoContext implementation
1014//-----------------------------------------------------------------------------
1015
e7f9f819
SC
1016class wxCairoOffsetHelper
1017{
1018public :
1019 wxCairoOffsetHelper( cairo_t* ctx , bool offset )
1020 {
1021 m_ctx = ctx;
1022 m_offset = offset;
1023 if ( m_offset )
1024 cairo_translate( m_ctx, 0.5, 0.5 );
1025 }
1026 ~wxCairoOffsetHelper( )
1027 {
1028 if ( m_offset )
1029 cairo_translate( m_ctx, -0.5, -0.5 );
1030 }
1031public :
1032 cairo_t* m_ctx;
1033 bool m_offset;
1034} ;
1035
c9008abe
RR
1036wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxPrinterDC& dc )
1037: wxGraphicsContext(renderer)
1038{
1039#ifdef __WXGTK20__
1040 const wxDCImpl *impl = dc.GetImpl();
1041 Init( (cairo_t*) impl->GetCairoContext() );
1042
c9008abe 1043 wxPoint org = dc.GetDeviceOrigin();
eaeb9985 1044 cairo_translate( m_context, org.x, org.y );
49ad157e 1045
c9008abe
RR
1046 double sx,sy;
1047 dc.GetUserScale( &sx, &sy );
eaeb9985 1048 cairo_scale( m_context, sx, sy );
c9008abe 1049
eaeb9985
RR
1050 org = dc.GetLogicalOrigin();
1051 cairo_translate( m_context, -org.x, -org.y );
c9008abe
RR
1052#endif
1053}
1054
00bd8e72
SC
1055wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC& dc )
1056: wxGraphicsContext(renderer)
1057{
c9008abe 1058#ifdef __WXGTK20__
888dde65 1059 wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
64a226f7 1060 Init( gdk_cairo_create( impldc->GetGDKWindow() ) );
49ad157e
VZ
1061
1062#if 0
c9008abe 1063 wxGraphicsMatrix matrix = CreateMatrix();
49ad157e 1064
c9008abe
RR
1065 wxPoint org = dc.GetDeviceOrigin();
1066 matrix.Translate( org.x, org.y );
49ad157e 1067
c9008abe
RR
1068 org = dc.GetLogicalOrigin();
1069 matrix.Translate( -org.x, -org.y );
1070
1071 double sx,sy;
1072 dc.GetUserScale( &sx, &sy );
1073 matrix.Scale( sx, sy );
1074
1075 ConcatTransform( matrix );
1076#endif
e7f9f819 1077#endif
c9008abe 1078
888dde65
RR
1079#ifdef __WXMAC__
1080 int width, height;
1081 dc.GetSize( &width, &height );
1082 CGContextRef cgcontext = (CGContextRef)dc.GetWindow()->MacGetCGContextRef();
1083 cairo_surface_t* surface = cairo_quartz_surface_create_for_cg_context(cgcontext, width, height);
1084 Init( cairo_create( surface ) );
1085 cairo_surface_destroy( surface );
1086#endif
1087}
1088
1089wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& dc )
1090: wxGraphicsContext(renderer)
1091{
c9008abe 1092#ifdef __WXGTK20__
888dde65
RR
1093 wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
1094 Init( gdk_cairo_create( impldc->GetGDKWindow() ) );
49ad157e
VZ
1095
1096#if 0
c9008abe 1097 wxGraphicsMatrix matrix = CreateMatrix();
49ad157e 1098
c9008abe
RR
1099 wxPoint org = dc.GetDeviceOrigin();
1100 matrix.Translate( org.x, org.y );
49ad157e 1101
c9008abe
RR
1102 org = dc.GetLogicalOrigin();
1103 matrix.Translate( -org.x, -org.y );
1104
1105 double sx,sy;
1106 dc.GetUserScale( &sx, &sy );
1107 matrix.Scale( sx, sy );
1108
1109 ConcatTransform( matrix );
64a226f7 1110#endif
c9008abe
RR
1111#endif
1112
e7f9f819
SC
1113#ifdef __WXMAC__
1114 int width, height;
1115 dc.GetSize( &width, &height );
1116 CGContextRef cgcontext = (CGContextRef)dc.GetWindow()->MacGetCGContextRef();
1117 cairo_surface_t* surface = cairo_quartz_surface_create_for_cg_context(cgcontext, width, height);
1118 Init( cairo_create( surface ) );
1119 cairo_surface_destroy( surface );
00bd8e72 1120#endif
00bd8e72
SC
1121}
1122
c9008abe 1123#ifdef __WXGTK20__
00bd8e72
SC
1124wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, GdkDrawable *drawable )
1125: wxGraphicsContext(renderer)
1126{
e7f9f819 1127 Init( gdk_cairo_create( drawable ) );
00bd8e72
SC
1128}
1129#endif
1130
1131wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, cairo_t *context )
1132: wxGraphicsContext(renderer)
1133{
e7f9f819 1134 Init( context );
184fc6c8
SC
1135}
1136
00bd8e72
SC
1137wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, wxWindow *window)
1138: wxGraphicsContext(renderer)
184fc6c8 1139{
00bd8e72
SC
1140#ifdef __WXGTK__
1141 // something along these lines (copied from dcclient)
1142
00bd8e72
SC
1143 // Some controls don't have m_wxwindow - like wxStaticBox, but the user
1144 // code should still be able to create wxClientDCs for them, so we will
1145 // use the parent window here then.
82a234fb 1146 if (window->m_wxwindow == NULL)
184fc6c8 1147 {
00bd8e72 1148 window = window->GetParent();
184fc6c8 1149 }
00bd8e72 1150
82a234fb 1151 wxASSERT_MSG( window->m_wxwindow, wxT("wxCairoContext needs a widget") );
00bd8e72 1152
82a234fb 1153 Init(gdk_cairo_create(window->GTKGetDrawingWindow()));
00bd8e72 1154#endif
00bd8e72
SC
1155}
1156
1157wxCairoContext::~wxCairoContext()
1158{
00bd8e72
SC
1159 if ( m_context )
1160 {
1161 PopState();
1162 PopState();
1163 cairo_destroy(m_context);
1164 }
1165}
1166
e7f9f819
SC
1167void wxCairoContext::Init(cairo_t *context)
1168{
1169 m_context = context ;
1170 PushState();
1171 PushState();
1172}
1173
00bd8e72 1174
d9485f89 1175void wxCairoContext::Clip( const wxRegion& region )
00bd8e72 1176{
d9485f89
RD
1177 // Create a path with all the rectangles in the region
1178 wxGraphicsPath path = GetRenderer()->CreatePath();
1179 wxRegionIterator ri(region);
1180 while (ri)
1181 {
1182 path.AddRectangle(ri.GetX(), ri.GetY(), ri.GetW(), ri.GetH());
82a234fb 1183 ++ri;
d9485f89 1184 }
49ad157e 1185
d9485f89
RD
1186 // Put it in the context
1187 cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ;
1188 cairo_append_path(m_context, cp);
1189
1190 // clip to that path
1191 cairo_clip(m_context);
49ad157e 1192 path.UnGetNativePath(cp);
00bd8e72
SC
1193}
1194
1195void wxCairoContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1196{
d9485f89
RD
1197 // Create a path with this rectangle
1198 wxGraphicsPath path = GetRenderer()->CreatePath();
1199 path.AddRectangle(x,y,w,h);
1200
1201 // Put it in the context
1202 cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ;
1203 cairo_append_path(m_context, cp);
1204
1205 // clip to that path
71696da0 1206 cairo_clip(m_context);
49ad157e 1207 path.UnGetNativePath(cp);
00bd8e72
SC
1208}
1209
1210void wxCairoContext::ResetClip()
1211{
d9485f89 1212 cairo_reset_clip(m_context);
00bd8e72
SC
1213}
1214
1215
0db8a70e 1216void wxCairoContext::StrokePath( const wxGraphicsPath& path )
00bd8e72 1217{
87752530 1218 if ( !m_pen.IsNull() )
49ad157e
VZ
1219 {
1220 wxCairoOffsetHelper helper( m_context, ShouldOffset() ) ;
0db8a70e 1221 cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ;
00bd8e72 1222 cairo_append_path(m_context,cp);
87752530 1223 ((wxCairoPenData*)m_pen.GetRefData())->Apply(this);
00bd8e72 1224 cairo_stroke(m_context);
0db8a70e 1225 path.UnGetNativePath(cp);
00bd8e72
SC
1226 }
1227}
1228
94a007ec 1229void wxCairoContext::FillPath( const wxGraphicsPath& path , wxPolygonFillMode fillStyle )
00bd8e72 1230{
87752530 1231 if ( !m_brush.IsNull() )
00bd8e72 1232 {
e7f9f819 1233 wxCairoOffsetHelper helper( m_context, ShouldOffset() ) ;
0db8a70e 1234 cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ;
00bd8e72 1235 cairo_append_path(m_context,cp);
87752530 1236 ((wxCairoBrushData*)m_brush.GetRefData())->Apply(this);
00bd8e72
SC
1237 cairo_set_fill_rule(m_context,fillStyle==wxODDEVEN_RULE ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
1238 cairo_fill(m_context);
0db8a70e 1239 path.UnGetNativePath(cp);
00bd8e72
SC
1240 }
1241}
1242
1243void wxCairoContext::Rotate( wxDouble angle )
1244{
1245 cairo_rotate(m_context,angle);
1246}
1247
1248void wxCairoContext::Translate( wxDouble dx , wxDouble dy )
1249{
1250 cairo_translate(m_context,dx,dy);
1251}
1252
1253void wxCairoContext::Scale( wxDouble xScale , wxDouble yScale )
1254{
1255 cairo_scale(m_context,xScale,yScale);
1256}
1257
1258// concatenates this transform with the current transform of this context
0db8a70e 1259void wxCairoContext::ConcatTransform( const wxGraphicsMatrix& matrix )
00bd8e72 1260{
0db8a70e 1261 cairo_transform(m_context,(const cairo_matrix_t *) matrix.GetNativeMatrix());
00bd8e72
SC
1262}
1263
1264// sets the transform of this context
0db8a70e 1265void wxCairoContext::SetTransform( const wxGraphicsMatrix& matrix )
00bd8e72 1266{
0db8a70e 1267 cairo_set_matrix(m_context,(const cairo_matrix_t*) matrix.GetNativeMatrix());
00bd8e72
SC
1268}
1269
1270// gets the matrix of this context
0db8a70e 1271wxGraphicsMatrix wxCairoContext::GetTransform() const
00bd8e72 1272{
0db8a70e
RD
1273 wxGraphicsMatrix matrix = CreateMatrix();
1274 cairo_get_matrix(m_context,(cairo_matrix_t*) matrix.GetNativeMatrix());
1275 return matrix;
00bd8e72
SC
1276}
1277
1278
1279
1280void wxCairoContext::PushState()
1281{
1282 cairo_save(m_context);
1283}
1284
1285void wxCairoContext::PopState()
1286{
1287 cairo_restore(m_context);
1288}
184fc6c8
SC
1289
1290void wxCairoContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1291{
d9485f89
RD
1292 wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap"));
1293
1294 cairo_surface_t* surface;
1295 int bw = bmp.GetWidth();
1296 int bh = bmp.GetHeight();
1297 wxBitmap bmpSource = bmp; // we need a non-const instance
1298 unsigned char* buffer = new unsigned char[bw*bh*4];
1299 wxUint32* data = (wxUint32*)buffer;
49ad157e 1300
d9485f89
RD
1301 // Create a surface object and copy the bitmap pixel data to it. if the
1302 // image has alpha (or a mask represented as alpha) then we'll use a
1303 // different format and iterator than if it doesn't...
1304 if (bmpSource.HasAlpha() || bmpSource.GetMask())
1305 {
1306 surface = cairo_image_surface_create_for_data(
1307 buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4);
1308 wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
1309 wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
49ad157e 1310
d9485f89
RD
1311 wxAlphaPixelData::Iterator p(pixData);
1312 for (int y=0; y<bh; y++)
1313 {
1314 wxAlphaPixelData::Iterator rowStart = p;
1315 for (int x=0; x<bw; x++)
1316 {
1317 // Each pixel in CAIRO_FORMAT_ARGB32 is a 32-bit quantity,
1318 // with alpha in the upper 8 bits, then red, then green, then
1319 // blue. The 32-bit quantities are stored native-endian.
1320 // Pre-multiplied alpha is used.
1321 unsigned char alpha = p.Alpha();
1322 if (alpha == 0)
1323 *data = 0;
1324 else
49ad157e
VZ
1325 *data = ( alpha << 24
1326 | (p.Red() * alpha/255) << 16
1327 | (p.Green() * alpha/255) << 8
d9485f89
RD
1328 | (p.Blue() * alpha/255) );
1329 ++data;
1330 ++p;
1331 }
1332 p = rowStart;
1333 p.OffsetY(pixData, 1);
49ad157e 1334 }
d9485f89
RD
1335 }
1336 else // no alpha
1337 {
1338 surface = cairo_image_surface_create_for_data(
1339 buffer, CAIRO_FORMAT_RGB24, bw, bh, bw*4);
1340 wxNativePixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
1341 wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
49ad157e 1342
d9485f89
RD
1343 wxNativePixelData::Iterator p(pixData);
1344 for (int y=0; y<bh; y++)
1345 {
1346 wxNativePixelData::Iterator rowStart = p;
1347 for (int x=0; x<bw; x++)
1348 {
1349 // Each pixel in CAIRO_FORMAT_RGB24 is a 32-bit quantity, with
1350 // the upper 8 bits unused. Red, Green, and Blue are stored in
1351 // the remaining 24 bits in that order. The 32-bit quantities
1352 // are stored native-endian.
1353 *data = ( p.Red() << 16 | p.Green() << 8 | p.Blue() );
1354 ++data;
1355 ++p;
1356 }
1357 p = rowStart;
1358 p.OffsetY(pixData, 1);
49ad157e 1359 }
d9485f89
RD
1360 }
1361
49ad157e 1362
d9485f89 1363 PushState();
49ad157e 1364
d9485f89
RD
1365 // In case we're scaling the image by using a width and height different
1366 // than the bitmap's size create a pattern transformation on the surface and
1367 // draw the transformed pattern.
1368 cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
1369 wxDouble scaleX = w / bw;
1370 wxDouble scaleY = h / bh;
1371 cairo_scale(m_context, scaleX, scaleY);
1372
1373 // prepare to draw the image
1374 cairo_translate(m_context, x, y);
1375 cairo_set_source(m_context, pattern);
1376 // use the original size here since the context is scaled already...
1377 cairo_rectangle(m_context, 0, 0, bw, bh);
1378 // fill the rectangle using the pattern
1379 cairo_fill(m_context);
1380
1381 // clean up
1382 cairo_pattern_destroy(pattern);
1383 cairo_surface_destroy(surface);
1384 delete [] buffer;
1385 PopState();
184fc6c8
SC
1386}
1387
1388void wxCairoContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1389{
d9485f89
RD
1390 // An icon is a bitmap on wxGTK, so do this the easy way. When we want to
1391 // start using the Cairo backend on other platforms then we may need to
1392 // fiddle with this...
1393 DrawBitmap(icon, x, y, w, h);
184fc6c8
SC
1394}
1395
1396
0b7dce54 1397void wxCairoContext::DoDrawText(const wxString& str, wxDouble x, wxDouble y)
184fc6c8 1398{
0b7dce54
VZ
1399 wxCHECK_RET( !m_font.IsNull(),
1400 wxT("wxCairoContext::DrawText - no valid font set") );
1011fbeb
SC
1401
1402 if ( str.empty())
d9485f89 1403 return;
84f67b11 1404
10c508ef 1405 const wxCharBuffer data = str.utf8_str();
e7f9f819
SC
1406 if ( !data )
1407 return;
0b7dce54 1408
84f67b11
SC
1409 ((wxCairoFontData*)m_font.GetRefData())->Apply(this);
1410
0b7dce54
VZ
1411#ifdef __WXGTK__
1412 size_t datalen = strlen(data);
1413
e7f9f819 1414 PangoLayout *layout = pango_cairo_create_layout (m_context);
0d19936d
FM
1415 wxCairoFontData* font_data = (wxCairoFontData*) m_font.GetRefData();
1416 pango_layout_set_font_description( layout, font_data->GetFont());
84f67b11 1417 pango_layout_set_text(layout, data, datalen);
0d19936d
FM
1418
1419 if (font_data->GetUnderlined())
1420 {
1421 PangoAttrList *attrs = pango_attr_list_new();
1422 PangoAttribute *attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
1423 pango_attr_list_insert(attrs, attr);
1424 pango_layout_set_attributes(layout, attrs);
1425 pango_attr_list_unref(attrs);
1426 }
1427
e7f9f819
SC
1428 cairo_move_to(m_context, x, y);
1429 pango_cairo_show_layout (m_context, layout);
1430
1431 g_object_unref (layout);
1432#else
d9485f89
RD
1433 // Cairo's x,y for drawing text is at the baseline, so we need to adjust
1434 // the position we move to by the ascent.
1435 cairo_font_extents_t fe;
1436 cairo_font_extents(m_context, &fe);
1437 cairo_move_to(m_context, x, y+fe.ascent);
49ad157e 1438
0b7dce54 1439 cairo_show_text(m_context, data);
e7f9f819 1440#endif
184fc6c8
SC
1441}
1442
1443void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
1444 wxDouble *descent, wxDouble *externalLeading ) const
1445{
1011fbeb
SC
1446 wxCHECK_RET( !m_font.IsNull(), wxT("wxCairoContext::GetTextExtent - no valid font set") );
1447
e7f9f819
SC
1448 if ( width )
1449 *width = 0;
1450 if ( height )
1451 *height = 0;
1452 if ( descent )
1453 *descent = 0;
1454 if ( externalLeading )
1455 *externalLeading = 0;
1456
1011fbeb 1457 if ( str.empty())
d9485f89
RD
1458 return;
1459
e7f9f819
SC
1460#ifdef __WXGTK__
1461 int w, h;
49ad157e 1462
e7f9f819 1463 PangoLayout *layout = pango_cairo_create_layout (m_context);
84f67b11 1464 pango_layout_set_font_description( layout, ((wxCairoFontData*)m_font.GetRefData())->GetFont());
10c508ef 1465 const wxCharBuffer data = str.utf8_str();
84f67b11 1466 if ( !data )
e7f9f819
SC
1467 {
1468 return;
1469 }
84f67b11 1470 pango_layout_set_text( layout, data, strlen(data) );
e7f9f819
SC
1471 pango_layout_get_pixel_size (layout, &w, &h);
1472 if ( width )
1473 *width = w;
1474 if ( height )
1475 *height = h;
1476 if (descent)
1477 {
1478 PangoLayoutIter *iter = pango_layout_get_iter(layout);
1479 int baseline = pango_layout_iter_get_baseline(iter);
1480 pango_layout_iter_free(iter);
1481 *descent = h - PANGO_PIXELS(baseline);
1482 }
1483 g_object_unref (layout);
1484#else
d9485f89
RD
1485 ((wxCairoFontData*)m_font.GetRefData())->Apply((wxCairoContext*)this);
1486
1487 if (width)
1488 {
1489 const wxWX2MBbuf buf(str.mb_str(wxConvUTF8));
1490 cairo_text_extents_t te;
1491 cairo_text_extents(m_context, buf, &te);
1492 *width = te.width;
1493 }
1494
1495 if (height || descent || externalLeading)
1496 {
1497 cairo_font_extents_t fe;
1498 cairo_font_extents(m_context, &fe);
49ad157e 1499
3e700936 1500 // some backends have negative descents
49ad157e 1501
3e700936
SC
1502 if ( fe.descent < 0 )
1503 fe.descent = -fe.descent;
49ad157e 1504
3e700936
SC
1505 if ( fe.height < (fe.ascent + fe.descent ) )
1506 {
1507 // some backends are broken re height ... (eg currently ATSUI)
1508 fe.height = fe.ascent + fe.descent;
1509 }
49ad157e 1510
d9485f89
RD
1511 if (height)
1512 *height = fe.height;
1513 if ( descent )
1514 *descent = fe.descent;
1515 if ( externalLeading )
1516 *externalLeading = wxMax(0, fe.height - (fe.ascent + fe.descent));
1517 }
e7f9f819 1518#endif
184fc6c8
SC
1519}
1520
1521void wxCairoContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
1522{
1523 widths.Empty();
1524 widths.Add(0, text.length());
1525
1011fbeb
SC
1526 wxCHECK_RET( !m_font.IsNull(), wxT("wxCairoContext::GetPartialTextExtents - no valid font set") );
1527
184fc6c8
SC
1528 if (text.empty())
1529 return;
00bd8e72
SC
1530
1531 // TODO
184fc6c8
SC
1532}
1533
49ad157e 1534void * wxCairoContext::GetNativeContext()
184fc6c8 1535{
00bd8e72
SC
1536 return m_context;
1537}
184fc6c8 1538
49ad157e
VZ
1539// Cairo doesn't support bitwise logical function (a.k.a. ROP, raster output
1540// mode). Cairo supports Porter-Duff compositing operators, but they are quite
1541// different, although in some cases have similar names.
89efaf2b 1542bool wxCairoContext::SetLogicalFunction( wxRasterOperationMode function )
49ad157e
VZ
1543{
1544 if (m_logicalFunction == function)
1545 return true;
1546
1547 cairo_operator_t op;
1548
1549 switch ( function )
1550 {
1551 case wxCOPY: // (default) src
1552 op = CAIRO_OPERATOR_OVER; // (also default)
1553 break;
1554 case wxOR: // src OR dst
1555 op = CAIRO_OPERATOR_ADD;
1556 break;
1557 case wxNO_OP: // dst
1558 op = CAIRO_OPERATOR_DEST; // ignore the source
1559 break;
1560 case wxCLEAR: // 0
1561 op = CAIRO_OPERATOR_CLEAR;// clear dst
1562 break;
1563
1564 case wxAND: // src AND dst
1565 case wxAND_INVERT: // (NOT src) AND dst
1566 case wxAND_REVERSE:// src AND (NOT dst)
1567 case wxEQUIV: // (NOT src) XOR dst
1568 case wxINVERT: // NOT dst
1569 case wxNAND: // (NOT src) OR (NOT dst)
1570 case wxNOR: // (NOT src) AND (NOT dst)
1571 case wxOR_INVERT: // (NOT src) OR dst
1572 case wxOR_REVERSE: // src OR (NOT dst)
1573 case wxSET: // 1
1574 case wxSRC_INVERT: // NOT src
1575 //wxXOR does _not_ correspond to CAIRO_OPERATOR_XOR
1576 case wxXOR: // src XOR dst
1577 default:
1578 return false;
1579 }
1580
1581 m_logicalFunction = function;
1582 cairo_set_operator(m_context, op);
1583 return true;
1584}
1585
1586
00bd8e72
SC
1587//-----------------------------------------------------------------------------
1588// wxCairoRenderer declaration
1589//-----------------------------------------------------------------------------
1590
1591class WXDLLIMPEXP_CORE wxCairoRenderer : public wxGraphicsRenderer
1592{
1593public :
1594 wxCairoRenderer() {}
1595
1596 virtual ~wxCairoRenderer() {}
1597
1598 // Context
1599
1600 virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
773ccc31 1601 virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc);
0b822969 1602 virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc);
773ccc31 1603
00bd8e72
SC
1604 virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
1605
1606 virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
1607
1608 virtual wxGraphicsContext * CreateContext( wxWindow* window );
1609
091ef146
SC
1610 virtual wxGraphicsContext * CreateMeasuringContext();
1611
00bd8e72
SC
1612 // Path
1613
0db8a70e 1614 virtual wxGraphicsPath CreatePath();
00bd8e72
SC
1615
1616 // Matrix
1617
49ad157e 1618 virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
00bd8e72
SC
1619 wxDouble tx=0.0, wxDouble ty=0.0);
1620
1621
87752530 1622 virtual wxGraphicsPen CreatePen(const wxPen& pen) ;
00bd8e72 1623
87752530 1624 virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
00bd8e72
SC
1625
1626 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
49ad157e 1627 virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
00bd8e72
SC
1628 const wxColour&c1, const wxColour&c2) ;
1629
49ad157e 1630 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
00bd8e72 1631 // with radius r and color cColor
87752530 1632 virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
00bd8e72
SC
1633 const wxColour &oColor, const wxColour &cColor) ;
1634
1635 // sets the font
87752530 1636 virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
00bd8e72 1637
d974a494
RR
1638 // create a native bitmap representation
1639#if 0
1640 virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap )
1641 {
1642 return wxGraphicsBitmap;
1643 }
49ad157e 1644
d974a494
RR
1645 // create a subimage from a native image representation
1646 virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1647 {
1648 return wxGraphicsBitmap;
1649 }
1650#endif
1651
00bd8e72
SC
1652private :
1653 DECLARE_DYNAMIC_CLASS_NO_COPY(wxCairoRenderer)
1654} ;
1655
1656//-----------------------------------------------------------------------------
1657// wxCairoRenderer implementation
1658//-----------------------------------------------------------------------------
1659
1660IMPLEMENT_DYNAMIC_CLASS(wxCairoRenderer,wxGraphicsRenderer)
1661
1662static wxCairoRenderer gs_cairoGraphicsRenderer;
3e700936
SC
1663// temporary hack to allow creating a cairo context on any platform
1664extern wxGraphicsRenderer* gCairoRenderer;
1665wxGraphicsRenderer* gCairoRenderer = &gs_cairoGraphicsRenderer;
00bd8e72
SC
1666
1667#ifdef __WXGTK__
1668wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
1669{
1670 return &gs_cairoGraphicsRenderer;
184fc6c8 1671}
00bd8e72 1672#endif
184fc6c8 1673
00bd8e72 1674wxGraphicsContext * wxCairoRenderer::CreateContext( const wxWindowDC& dc)
539e2795 1675{
00bd8e72
SC
1676 return new wxCairoContext(this,dc);
1677}
1678
773ccc31
SC
1679wxGraphicsContext * wxCairoRenderer::CreateContext( const wxMemoryDC& dc)
1680{
888dde65 1681 return new wxCairoContext(this,dc);
773ccc31 1682}
773ccc31 1683
0b822969
RR
1684wxGraphicsContext * wxCairoRenderer::CreateContext( const wxPrinterDC& dc)
1685{
c9008abe 1686#ifdef __WXGTK20__
0b822969
RR
1687 const wxDCImpl *impl = dc.GetImpl();
1688 cairo_t* context = (cairo_t*) impl->GetCairoContext();
1689 if (context)
c9008abe 1690 return new wxCairoContext(this,dc);
0b822969 1691 else
c9008abe 1692#endif
0b822969
RR
1693 return NULL;
1694}
1695
00bd8e72
SC
1696wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeContext( void * context )
1697{
1698 return new wxCairoContext(this,(cairo_t*)context);
1699}
1700
1701
1702wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeWindow( void * window )
1703{
1704#ifdef __WXGTK__
ed1b38a8 1705 return new wxCairoContext(this,(GdkDrawable*)window);
00bd8e72
SC
1706#else
1707 return NULL;
1708#endif
1709}
1710
091ef146
SC
1711wxGraphicsContext * wxCairoRenderer::CreateMeasuringContext()
1712{
1713 return NULL;
1714 // TODO
1715}
1716
00bd8e72
SC
1717wxGraphicsContext * wxCairoRenderer::CreateContext( wxWindow* window )
1718{
1719 return new wxCairoContext(this, window );
1720}
1721
1722// Path
1723
0db8a70e 1724wxGraphicsPath wxCairoRenderer::CreatePath()
00bd8e72 1725{
0db8a70e
RD
1726 wxGraphicsPath path;
1727 path.SetRefData( new wxCairoPathData(this) );
1728 return path;
539e2795
SC
1729}
1730
00bd8e72
SC
1731
1732// Matrix
1733
49ad157e 1734wxGraphicsMatrix wxCairoRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
0db8a70e 1735 wxDouble tx, wxDouble ty)
00bd8e72 1736
184fc6c8 1737{
0db8a70e
RD
1738 wxGraphicsMatrix m;
1739 wxCairoMatrixData* data = new wxCairoMatrixData( this );
1740 data->Set( a,b,c,d,tx,ty ) ;
1741 m.SetRefData(data);
00bd8e72 1742 return m;
7ba86d93
RD
1743}
1744
49ad157e 1745wxGraphicsPen wxCairoRenderer::CreatePen(const wxPen& pen)
539e2795 1746{
00bd8e72 1747 if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
87752530 1748 return wxNullGraphicsPen;
00bd8e72 1749 else
87752530
SC
1750 {
1751 wxGraphicsPen p;
1752 p.SetRefData(new wxCairoPenData( this, pen ));
1753 return p;
1754 }
539e2795
SC
1755}
1756
49ad157e 1757wxGraphicsBrush wxCairoRenderer::CreateBrush(const wxBrush& brush )
539e2795 1758{
00bd8e72 1759 if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
87752530 1760 return wxNullGraphicsBrush;
00bd8e72 1761 else
87752530
SC
1762 {
1763 wxGraphicsBrush p;
1764 p.SetRefData(new wxCairoBrushData( this, brush ));
1765 return p;
1766 }
00bd8e72
SC
1767}
1768
1769// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
49ad157e
VZ
1770wxGraphicsBrush wxCairoRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
1771 const wxColour&c1, const wxColour&c2)
00bd8e72 1772{
87752530
SC
1773 wxGraphicsBrush p;
1774 wxCairoBrushData* d = new wxCairoBrushData( this );
1775 d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
1776 p.SetRefData(d);
1777 return p;
00bd8e72
SC
1778}
1779
49ad157e 1780// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
00bd8e72 1781// with radius r and color cColor
87752530 1782wxGraphicsBrush wxCairoRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
49ad157e 1783 const wxColour &oColor, const wxColour &cColor)
00bd8e72 1784{
87752530
SC
1785 wxGraphicsBrush p;
1786 wxCairoBrushData* d = new wxCairoBrushData( this );
1787 d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
1788 p.SetRefData(d);
1789 return p;
00bd8e72
SC
1790}
1791
1792// sets the font
49ad157e 1793wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour &col )
00bd8e72
SC
1794{
1795 if ( font.Ok() )
49ad157e 1796 {
87752530
SC
1797 wxGraphicsFont p;
1798 p.SetRefData(new wxCairoFontData( this , font, col ));
1799 return p;
1800 }
00bd8e72 1801 else
87752530 1802 return wxNullGraphicsFont;
539e2795
SC
1803}
1804
7ba86d93 1805#endif // wxUSE_GRAPHICS_CONTEXT