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