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