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