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