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