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