1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/graphicc.cpp 
   3 // Purpose:     cairo device context class 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) 2006 Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #include "wx/wxprec.h" 
  22 #include "wx/window.h" 
  25 #include "wx/dialog.h" 
  27 #include "wx/bitmap.h" 
  28 #include "wx/dcmemory.h" 
  31 #include "wx/dcprint.h" 
  32 #include "wx/module.h" 
  35 #include "wx/graphics.h" 
  37 #if wxUSE_GRAPHICS_CONTEXT 
  43 //----------------------------------------------------------------------------- 
  45 //----------------------------------------------------------------------------- 
  47 const double RAD2DEG 
= 180.0 / M_PI
; 
  49 //----------------------------------------------------------------------------- 
  51 //----------------------------------------------------------------------------- 
  53 static inline double dmin(double a
, double b
) 
  57 static inline double dmax(double a
, double b
) 
  62 static inline double DegToRad(double deg
) 
  64     return (deg 
* M_PI
) / 180.0; 
  66 static inline double RadToDeg(double deg
) 
  68     return (deg 
* 180.0) / M_PI
; 
  71 //----------------------------------------------------------------------------- 
  72 // device context implementation 
  74 // more and more of the dc functionality should be implemented by calling 
  75 // the appropricate wxCairoContext, but we will have to do that step by step 
  76 // also coordinate conversions should be moved to native matrix ops 
  77 //----------------------------------------------------------------------------- 
  79 // we always stock two context states, one at entry, to be able to preserve the 
  80 // state we were called with, the other one after changing to HI Graphics orientation 
  81 // (this one is used for getting back clippings etc) 
  83 //----------------------------------------------------------------------------- 
  84 // wxGraphicsPath implementation 
  85 //----------------------------------------------------------------------------- 
  87 // TODO remove this dependency (gdiplus needs the macros) 
  90 #define max(a,b)            (((a) > (b)) ? (a) : (b)) 
  94 #define min(a,b)            (((a) < (b)) ? (a) : (b)) 
 100 class WXDLLEXPORT wxCairoPath 
: public wxGraphicsPath
 
 102     DECLARE_NO_COPY_CLASS(wxCairoPath
) 
 109     // These are the path primitives from which everything else can be constructed 
 112     // begins a new subpath at (x,y) 
 113     virtual void MoveToPoint( wxDouble x
, wxDouble y 
); 
 115     // adds a straight line from the current point to (x,y) 
 116     virtual void AddLineToPoint( wxDouble x
, wxDouble y 
); 
 118     // adds a cubic Bezier curve from the current point, using two control points and an end point 
 119     virtual void AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y 
); 
 122     // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle 
 123     virtual void AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise 
) ; 
 125     // gets the last point of the current path, (0,0) if not yet set 
 126     virtual void GetCurrentPoint( wxDouble
& x
, wxDouble
&y
) ; 
 128     // closes the current sub-path 
 129     virtual void CloseSubpath(); 
 132     // These are convenience functions which - if not available natively will be assembled 
 133     // using the primitives from above 
 138     // appends a rectangle as a new closed subpath  
 139     virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) ; 
 140     // appends an ellipsis as a new closed subpath fitting the passed rectangle 
 141     virtual void AddEllipsis( wxDouble x, wxDouble y, wxDouble w , wxDouble h ) ; 
 143     // 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) 
 144     virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )  ; 
 147     cairo_path_t
* GetPath() const; 
 149     cairo_t
* m_pathContext
; 
 152 wxCairoPath::wxCairoPath() 
 154     cairo_surface_t
* surface 
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
,1,1); 
 155     m_pathContext 
= cairo_create(surface
); 
 156     cairo_surface_destroy (surface
); 
 159 wxCairoPath::~wxCairoPath() 
 161     cairo_destroy(m_pathContext
); 
 164 cairo_path_t
* wxCairoPath::GetPath() const 
 166     return cairo_copy_path(m_pathContext
) ; 
 173 void wxCairoPath::MoveToPoint( wxDouble x 
, wxDouble y 
) 
 175     cairo_move_to(m_pathContext
,x
,y
); 
 178 void wxCairoPath::AddLineToPoint( wxDouble x 
, wxDouble y 
) 
 180     cairo_line_to(m_pathContext
,x
,y
); 
 183 void wxCairoPath::CloseSubpath() 
 185     cairo_close_path(m_pathContext
); 
 188 void wxCairoPath::AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y 
) 
 190     cairo_curve_to(m_pathContext
,cx1
,cy1
,cx2
,cy2
,x
,y
); 
 193 // gets the last point of the current path, (0,0) if not yet set 
 194 void wxCairoPath::GetCurrentPoint( wxDouble
& x
, wxDouble
&y
) 
 197     cairo_get_current_point(m_pathContext
,&dx
,&dy
); 
 202 void wxCairoPath::AddArc( wxDouble x
, wxDouble y
, wxDouble r
, double startAngle
, double endAngle
, bool clockwise 
) 
 204     // as clockwise means positive in our system (y pointing downwards)  
 205     // TODO make this interpretation dependent of the 
 207     if ( clockwise
||(endAngle
-startAngle
)>=2*M_PI
) 
 208         cairo_arc(m_pathContext
,x
,y
,r
,startAngle
,endAngle
); 
 210         cairo_arc_negative(m_pathContext
,x
,y
,r
,startAngle
,endAngle
); 
 214 void wxCairoPath::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) 
 216     m_path->AddRectangle(RectF(x,y,w,h)); 
 223 // closes the current subpath 
 224 void wxCairoPath::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )  
 226 //    CGPathAddArcToPoint( m_path, NULL , x1, y1, x2, y2, r);  
 231 class WXDLLEXPORT wxCairoContext 
: public wxGraphicsContext
 
 233     DECLARE_NO_COPY_CLASS(wxCairoContext
) 
 236     wxCairoContext( const wxWindowDC
& dc 
); 
 238     virtual ~wxCairoContext(); 
 240     virtual void Clip( const wxRegion 
®ion 
); 
 242     // clips drawings to the rect 
 243     virtual void Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
); 
 245         // resets the clipping to original extent 
 246         virtual void ResetClip(); 
 248         virtual void * GetNativeContext(); 
 250     virtual void StrokePath( const wxGraphicsPath 
*p 
); 
 251     virtual void FillPath( const wxGraphicsPath 
*p 
, int fillStyle 
= wxWINDING_RULE 
); 
 253     virtual wxGraphicsPath
* CreatePath(); 
 254     virtual void SetPen( const wxPen 
&pen 
); 
 255     virtual void SetBrush( const wxBrush 
&brush 
); 
 256     virtual void SetLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, const wxColour
&c1
, const wxColour
&c2
) ; 
 257     virtual void SetRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
, 
 258                                          const wxColour 
&oColor
, const wxColour 
&cColor
); 
 260     virtual void Translate( wxDouble dx 
, wxDouble dy 
); 
 261     virtual void Scale( wxDouble xScale 
, wxDouble yScale 
); 
 262     virtual void Rotate( wxDouble angle 
); 
 264     virtual void DrawBitmap( const wxBitmap 
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
); 
 265     virtual void DrawIcon( const wxIcon 
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
); 
 266     virtual void PushState(); 
 267     virtual void PopState(); 
 269     virtual void SetFont( const wxFont 
&font 
); 
 270     virtual void SetTextColor( const wxColour 
&col 
); 
 271     virtual void DrawText( const wxString 
&str
, wxDouble x
, wxDouble y
); 
 272     virtual void GetTextExtent( const wxString 
&str
, wxDouble 
*width
, wxDouble 
*height
, 
 273                                 wxDouble 
*descent
, wxDouble 
*externalLeading 
) const; 
 274     virtual void GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const; 
 278     bool m_penTransparent
; 
 279     bool m_brushTransparent
; 
 283     cairo_pattern_t
* m_brushPattern
; 
 284     wxColour m_textColour
; 
 290 //----------------------------------------------------------------------------- 
 291 // wxCairoContext implementation 
 292 //----------------------------------------------------------------------------- 
 294 wxCairoContext::wxCairoContext( const wxWindowDC
& dc  
) 
 296     m_context 
= gdk_cairo_create( dc
.m_window 
) ; 
 299     m_penTransparent 
= true; 
 300     m_brushTransparent 
= true; 
 301     m_brushPattern 
= NULL 
; 
 304 wxCairoContext::~wxCairoContext() 
 310         cairo_destroy(m_context
); 
 311         if ( m_brushPattern 
) 
 312             cairo_pattern_destroy(m_brushPattern
); 
 317 void wxCairoContext::Clip( const wxRegion 
& WXUNUSED(region
) ) 
 322 void wxCairoContext::Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
 327 void wxCairoContext::ResetClip() 
 333 void wxCairoContext::StrokePath( const wxGraphicsPath 
*p 
) 
 335     if ( m_penTransparent 
) 
 338     const wxCairoPath
* path 
= (const wxCairoPath 
*) p
; 
 339     cairo_path_t
* cp 
= path
->GetPath() ; 
 340     cairo_append_path(m_context
,cp
); 
 344     // TODO: * m_dc->m_scaleX 
 345     double penWidth 
= m_pen
.GetWidth(); 
 349     cairo_set_line_width(m_context
,penWidth
); 
 350     cairo_set_source_rgba(m_context
,m_pen
.GetColour().Red()/255.0, 
 351                           m_pen
.GetColour().Green()/255.0, m_pen
.GetColour().Blue()/255.0,m_pen
.GetColour().Alpha()/255.0); 
 353     cairo_line_cap_t cap
; 
 354     switch ( m_pen
.GetCap() ) 
 357         cap 
= CAIRO_LINE_CAP_ROUND
; 
 360     case wxCAP_PROJECTING 
: 
 361         cap 
= CAIRO_LINE_CAP_SQUARE
; 
 365         cap 
= CAIRO_LINE_CAP_BUTT
; 
 369         cap 
= CAIRO_LINE_CAP_BUTT
; 
 372     cairo_set_line_cap(m_context
,cap
); 
 374     cairo_line_join_t join
; 
 375     switch ( m_pen
.GetJoin() ) 
 378         join 
= CAIRO_LINE_JOIN_BEVEL
; 
 382         join 
= CAIRO_LINE_JOIN_MITER
; 
 386         join 
= CAIRO_LINE_JOIN_ROUND
; 
 390         join 
= CAIRO_LINE_JOIN_MITER
; 
 393     cairo_set_line_join(m_context
,join
); 
 396     const double * dashes 
= NULL
; 
 399     const double dashUnit 
= penWidth 
< 1.0 ? 1.0 : penWidth
; 
 401     double *userLengths 
= NULL
; 
 402     const double dotted
[] = 
 404             dashUnit 
, dashUnit 
+ 2.0 
 406     const double short_dashed
[] = 
 410     const double dashed
[] = 
 414     const double dotted_dashed
[] = 
 416             9.0 , 6.0 , 3.0 , 3.0 
 419     switch ( m_pen
.GetStyle() ) 
 426         num_dashes 
= WXSIZEOF(dotted
) 
 432         num_dashes 
= WXSIZEOF(dashed
); 
 437         num_dashes 
= WXSIZEOF(short_dashed
); 
 442         num_dashes 
= WXSIZEOF(dotted_dashed
); 
 448             num_dashes 
= m_pen
.GetDashes( &wxdashes 
) ; 
 449             if ((wxdashes 
!= NULL
) && (num_dashes 
> 0)) 
 451                 userLengths 
= new double[num_dashes
] ; 
 452                 for ( int i 
= 0 ; i 
< num_dashes 
; ++i 
) 
 454                     userLengths
[i
] = wxdashes
[i
] * dashUnit 
; 
 456                     if ( i 
% 2 == 1 && userLengths
[i
] < dashUnit 
+ 2.0 ) 
 457                         userLengths
[i
] = dashUnit 
+ 2.0 ; 
 458                     else if ( i 
% 2 == 0 && userLengths
[i
] < dashUnit 
) 
 459                         userLengths
[i
] = dashUnit 
; 
 462             dashes 
= userLengths 
; 
 468                         wxBitmap* bmp = pen.GetStipple(); 
 469                         if ( bmp && bmp->Ok() ) 
 471                             wxDELETE( m_penImage ); 
 472                             wxDELETE( m_penBrush ); 
 473                             m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE()); 
 474                             m_penBrush = new TextureBrush(m_penImage); 
 475                             m_pen->SetBrush( m_penBrush ); 
 481         if ( m_pen
.GetStyle() >= wxFIRST_HATCH 
&& m_pen
.GetStyle() <= wxLAST_HATCH 
) 
 484                         wxDELETE( m_penBrush ); 
 485                         HatchStyle style = HatchStyleHorizontal; 
 486                         switch( pen.GetStyle() ) 
 488                         case wxBDIAGONAL_HATCH : 
 489                             style = HatchStyleBackwardDiagonal; 
 491                         case wxCROSSDIAG_HATCH : 
 492                             style = HatchStyleDiagonalCross; 
 494                         case wxFDIAGONAL_HATCH : 
 495                             style = HatchStyleForwardDiagonal; 
 498                             style = HatchStyleCross; 
 500                         case wxHORIZONTAL_HATCH : 
 501                             style = HatchStyleHorizontal; 
 503                         case wxVERTICAL_HATCH : 
 504                             style = HatchStyleVertical; 
 508                         m_penBrush = new HatchBrush(style,Color( pen.GetColour().Alpha() , pen.GetColour().Red() , 
 509                             pen.GetColour().Green() , pen.GetColour().Blue() ), Color.Transparent ); 
 510                         m_pen->SetBrush( m_penBrush ) 
 516     cairo_set_dash(m_context
,(double*)dashes
,num_dashes
,offset
); 
 518         delete[] userLengths
; 
 519     cairo_stroke(m_context
); 
 520     cairo_path_destroy(cp
); 
 523 void wxCairoContext::FillPath( const wxGraphicsPath 
*p 
, int fillStyle 
) 
 525     if ( !m_brushTransparent 
) 
 527         const wxCairoPath
* path 
= (const wxCairoPath 
*) p
; 
 528         cairo_path_t
* cp 
= path
->GetPath() ; 
 529         cairo_append_path(m_context
,cp
); 
 531         if ( m_brushPattern 
) 
 533             cairo_set_source(m_context
,m_brushPattern
); 
 537             cairo_set_source_rgba(m_context
,m_brush
.GetColour().Red()/255.0, 
 538                                   m_brush
.GetColour().Green()/255.0, 
 539                                   m_brush
.GetColour().Blue()/255.0, 
 540                                   m_brush
.GetColour().Alpha()/255.0); 
 543         cairo_set_fill_rule(m_context
,fillStyle
==wxODDEVEN_RULE 
? CAIRO_FILL_RULE_EVEN_ODD 
: CAIRO_FILL_RULE_WINDING
); 
 544         cairo_fill(m_context
); 
 545         cairo_path_destroy(cp
); 
 549 wxGraphicsPath
* wxCairoContext::CreatePath() 
 551     return new wxCairoPath(); 
 554 void wxCairoContext::Rotate( wxDouble angle 
) 
 556     cairo_rotate(m_context
,angle
); 
 559 void wxCairoContext::Translate( wxDouble dx 
, wxDouble dy 
) 
 561     cairo_translate(m_context
,dx
,dy
); 
 564 void wxCairoContext::Scale( wxDouble xScale 
, wxDouble yScale 
) 
 566     cairo_scale(m_context
,xScale
,yScale
); 
 568         PointF penWidth( m_pen->GetWidth(), 0); 
 570         if ( !m_penTransparent ) 
 572                 m_context->GetTransform(&matrix); 
 573                 matrix.TransformVectors(&penWidth); 
 575         m_context->ScaleTransform(xScale,yScale); 
 576         if ( !m_penTransparent ) 
 578             m_context->GetTransform(&matrix); 
 580             matrix.TransformVectors(&penWidth) ; 
 581             m_pen->SetWidth( sqrt( penWidth.X*penWidth.X  + penWidth.Y*penWidth.Y)); 
 586 void wxCairoContext::PushState() 
 588     cairo_save(m_context
); 
 591 void wxCairoContext::PopState() 
 593     cairo_restore(m_context
); 
 596 void wxCairoContext::SetTextColor( const wxColour 
&col 
) 
 601 void wxCairoContext::SetPen( const wxPen 
&pen 
) 
 604     m_penTransparent 
= pen
.GetStyle() == wxTRANSPARENT
; 
 605     if ( m_penTransparent 
) 
 612                 wxBitmap* bmp = pen.GetStipple(); 
 613                 if ( bmp && bmp->Ok() ) 
 615                     wxDELETE( m_penImage ); 
 616                     wxDELETE( m_penBrush ); 
 617                     m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE()); 
 618                     m_penBrush = new TextureBrush(m_penImage); 
 619                     m_pen->SetBrush( m_penBrush ); 
 625             if ( pen.GetStyle() >= wxFIRST_HATCH && pen.GetStyle() <= wxLAST_HATCH ) 
 627                 wxDELETE( m_penBrush ); 
 628                 HatchStyle style = HatchStyleHorizontal; 
 629                 switch( pen.GetStyle() ) 
 631                 case wxBDIAGONAL_HATCH : 
 632                     style = HatchStyleBackwardDiagonal; 
 634                 case wxCROSSDIAG_HATCH : 
 635                     style = HatchStyleDiagonalCross; 
 637                 case wxFDIAGONAL_HATCH : 
 638                     style = HatchStyleForwardDiagonal; 
 641                     style = HatchStyleCross; 
 643                 case wxHORIZONTAL_HATCH : 
 644                     style = HatchStyleHorizontal; 
 646                 case wxVERTICAL_HATCH : 
 647                     style = HatchStyleVertical; 
 651                 m_penBrush = new HatchBrush(style,Color( pen.GetColour().Alpha() , pen.GetColour().Red() , 
 652                     pen.GetColour().Green() , pen.GetColour().Blue() ), Color.Transparent ); 
 653                 m_pen->SetBrush( m_penBrush ); 
 657         if ( dashStyle != DashStyleSolid ) 
 658             m_pen->SetDashStyle(dashStyle); 
 662 void wxCairoContext::SetBrush( const wxBrush 
&brush 
) 
 667         cairo_pattern_destroy(m_brushPattern
); 
 668         m_brushPattern 
= NULL
; 
 670     m_brushTransparent 
= brush
.GetStyle() == wxTRANSPARENT
; 
 672     if ( m_brushTransparent 
) 
 677         if ( brush.GetStyle() == wxSOLID) 
 679             m_brush = new SolidBrush( Color( brush.GetColour().Alpha() , brush.GetColour().Red() , 
 680                 brush.GetColour().Green() , brush.GetColour().Blue() ) ); 
 682         else if ( brush.IsHatch() ) 
 684             HatchStyle style = HatchStyleHorizontal; 
 685             switch( brush.GetStyle() ) 
 687             case wxBDIAGONAL_HATCH : 
 688                 style = HatchStyleBackwardDiagonal; 
 690             case wxCROSSDIAG_HATCH : 
 691                 style = HatchStyleDiagonalCross; 
 693             case wxFDIAGONAL_HATCH : 
 694                 style = HatchStyleForwardDiagonal; 
 697                 style = HatchStyleCross; 
 699             case wxHORIZONTAL_HATCH : 
 700                 style = HatchStyleHorizontal; 
 702             case wxVERTICAL_HATCH : 
 703                 style = HatchStyleVertical; 
 707             m_brush = new HatchBrush(style,Color( brush.GetColour().Alpha() , brush.GetColour().Red() , 
 708                 brush.GetColour().Green() , brush.GetColour().Blue() ), Color.Transparent ); 
 712             wxBitmap* bmp = brush.GetStipple(); 
 713             if ( bmp && bmp->Ok() ) 
 715                 wxDELETE( m_brushImage ); 
 716                 m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE()); 
 717                 m_brush = new TextureBrush(m_brushImage); 
 723 void wxCairoContext::SetLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, const wxColour
&c1
, const wxColour
&c2
) 
 725     if ( m_brushPattern 
) 
 727         cairo_pattern_destroy(m_brushPattern
); 
 731     m_brushTransparent 
= false; 
 732     m_brushPattern 
= cairo_pattern_create_linear(x1
,y1
,x2
,y2
); 
 733     cairo_pattern_add_color_stop_rgba(m_brushPattern
,0.0,c1
.Red()/255.0, 
 734                           c1
.Green()/255.0, c1
.Blue()/255.0,c1
.Alpha()/255.0); 
 735     cairo_pattern_add_color_stop_rgba(m_brushPattern
,1.0,c2
.Red()/255.0, 
 736                           c2
.Green()/255.0, c2
.Blue()/255.0,c2
.Alpha()/255.0); 
 737     wxASSERT_MSG(cairo_pattern_status(m_brushPattern
) == CAIRO_STATUS_SUCCESS
, wxT("Couldn't create cairo pattern")); 
 740 void wxCairoContext::SetRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
, 
 741         const wxColour 
&oColor
, const wxColour 
&cColor
) 
 743    if ( m_brushPattern 
) 
 745         cairo_pattern_destroy(m_brushPattern
); 
 749     m_brushTransparent 
= false; 
 750     m_brushPattern 
= cairo_pattern_create_radial(xo
,yo
,0.0,xc
,yc
,radius
); 
 751     cairo_pattern_add_color_stop_rgba(m_brushPattern
,0.0,oColor
.Red()/255.0, 
 752                           oColor
.Green()/255.0, oColor
.Blue()/255.0,oColor
.Alpha()/255.0); 
 753     cairo_pattern_add_color_stop_rgba(m_brushPattern
,1.0,cColor
.Red()/255.0, 
 754                           cColor
.Green()/255.0, cColor
.Blue()/255.0,cColor
.Alpha()/255.0); 
 755     wxASSERT_MSG(cairo_pattern_status(m_brushPattern
) == CAIRO_STATUS_SUCCESS
, wxT("Couldn't create cairo pattern")); 
 758 void wxCairoContext::DrawBitmap( const wxBitmap 
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
 761         Bitmap* image = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE()); 
 762         m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ; 
 767 void wxCairoContext::DrawIcon( const wxIcon 
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
 770         Bitmap* image = Bitmap::FromHICON((HICON)icon.GetHICON()); 
 771         m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ; 
 777 void wxCairoContext::DrawText( const wxString 
&str
, wxDouble x
, wxDouble y 
) 
 781     cairo_move_to(m_context
,x
,y
); 
 782     const wxWX2MBbuf 
buf(str
.mb_str(wxConvUTF8
)); 
 784     cairo_set_source_rgba(m_context
,m_textColour
.Red()/255.0, 
 785                           m_textColour
.Green()/255.0, m_textColour
.Blue()/255.0,m_textColour
.Alpha()/255.0); 
 786     cairo_show_text(m_context
,buf
); 
 788     // TODO m_backgroundMode == wxSOLID 
 791 void wxCairoContext::GetTextExtent( const wxString 
&str
, wxDouble 
*width
, wxDouble 
*height
, 
 792                                     wxDouble 
*descent
, wxDouble 
*externalLeading 
) const 
 795         wxWCharBuffer s = str.wc_str( *wxConvUI ); 
 798         m_font->GetFamily(&ffamily) ; 
 800         REAL factorY = m_context->GetDpiY() / 72.0 ; 
 802         REAL rDescent = ffamily.GetCellDescent(FontStyleRegular) * 
 803             m_font->GetSize() / ffamily.GetEmHeight(FontStyleRegular); 
 804         REAL rAscent = ffamily.GetCellAscent(FontStyleRegular) * 
 805             m_font->GetSize() / ffamily.GetEmHeight(FontStyleRegular); 
 806         REAL rHeight = ffamily.GetLineSpacing(FontStyleRegular) * 
 807             m_font->GetSize() / ffamily.GetEmHeight(FontStyleRegular); 
 810             *height = rHeight * factorY + 0.5 ; 
 812             *descent = rDescent * factorY + 0.5 ; 
 813         if ( externalLeading ) 
 814             *externalLeading = (rHeight - rAscent - rDescent) * factorY + 0.5 ; 
 815         // measuring empty strings is not guaranteed, so do it by hand 
 823             // MeasureString does return a rectangle that is way too large, so it is 
 825             RectF layoutRect(0,0, 100000.0f, 100000.0f); 
 826             StringFormat strFormat; 
 827             CharacterRange strRange(0,wcslen(s)); 
 828             strFormat.SetMeasurableCharacterRanges(1,&strRange); 
 830             m_context->MeasureCharacterRanges(s, -1 , m_font,layoutRect, &strFormat,1,®ion) ; 
 832             region.GetBounds(&bbox,m_context); 
 834                 *width = bbox.GetRight()-bbox.GetLeft()+0.5; 
 839 void wxCairoContext::GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const 
 842     widths
.Add(0, text
.length()); 
 847         wxWCharBuffer ws = text.wc_str( *wxConvUI ); 
 848         size_t len = wcslen( ws ) ; 
 849         wxASSERT_MSG(text.length() == len , wxT("GetPartialTextExtents not yet implemented for multichar situations")); 
 851         RectF layoutRect(0,0, 100000.0f, 100000.0f); 
 852         StringFormat strFormat; 
 854         CharacterRange* ranges = new CharacterRange[len] ; 
 855         Region* regions = new Region[len]; 
 856         for( int i = 0 ; i < len ; ++i) 
 858             ranges[i].First = i ; 
 859             ranges[i].Length = 1 ; 
 861         strFormat.SetMeasurableCharacterRanges(len,ranges); 
 862         m_context->MeasureCharacterRanges(ws, -1 , m_font,layoutRect, &strFormat,1,regions) ; 
 865         for ( int i = 0 ; i < len ; ++i) 
 867             regions[i].GetBounds(&bbox,m_context); 
 868             widths[i] = bbox.GetRight()-bbox.GetLeft(); 
 873 void wxCairoContext::SetFont( const wxFont 
&font 
) 
 875     cairo_select_font_face(m_context
,font
.GetFaceName().mb_str(wxConvUTF8
), 
 876                            font
.GetStyle() == wxFONTSTYLE_ITALIC 
? CAIRO_FONT_SLANT_ITALIC
:CAIRO_FONT_SLANT_NORMAL
, 
 877                            font
.GetWeight() == wxFONTWEIGHT_BOLD 
? CAIRO_FONT_WEIGHT_BOLD
:CAIRO_FONT_WEIGHT_NORMAL
); 
 879     cairo_set_font_size(m_context
,font
.GetPointSize()); 
 884 void * wxCairoContext::GetNativeContext()  
 889 wxGraphicsContext
* wxGraphicsContext::Create( const wxWindowDC
& dc 
) 
 891     return new wxCairoContext(dc
); 
 894 wxGraphicsContext
* wxGraphicsContext::Create( wxWindow 
* window 
) 
 899 wxGraphicsContext
* wxGraphicsContext::CreateFromNative( void * context 
) 
 904 #endif  // wxUSE_GRAPHICS_CONTEXT