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