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