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