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