1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/graphics.cpp 
   3 // Purpose:     wxGCDC class 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) 2006 Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #include "wx/wxprec.h" 
  20 #if wxUSE_GRAPHICS_CONTEXT 
  23     #include "wx/msw/wrapcdlg.h" 
  25     #include "wx/window.h" 
  27     #include "wx/dialog.h" 
  29     #include "wx/bitmap.h" 
  32     #include "wx/module.h" 
  33     // include all dc types that are used as a param 
  35     #include "wx/dcclient.h" 
  36     #include "wx/dcmemory.h" 
  37     #include "wx/dcprint.h" 
  40 #include "wx/private/graphics.h" 
  41 #include "wx/msw/wrapgdip.h" 
  42 #include "wx/msw/dc.h" 
  43 #include "wx/dcgraph.h" 
  45 #include "wx/msw/private.h" // needs to be before #include <commdlg.h> 
  47 #if wxUSE_COMMON_DIALOGS && !defined(__WXMICROWIN__) 
  53 WX_DECLARE_STACK(GraphicsState
, GraphicsStates
); 
  58 //----------------------------------------------------------------------------- 
  60 //----------------------------------------------------------------------------- 
  62 const double RAD2DEG 
= 180.0 / M_PI
; 
  64 //----------------------------------------------------------------------------- 
  66 //----------------------------------------------------------------------------- 
  68 inline double dmin(double a
, double b
) { return a 
< b 
? a 
: b
; } 
  69 inline double dmax(double a
, double b
) { return a 
> b 
? a 
: b
; } 
  71 inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  72 inline double RadToDeg(double deg
) { return (deg 
* 180.0) / M_PI
; } 
  74 // translate a wxColour to a Color 
  75 inline Color 
wxColourToColor(const wxColour
& col
) 
  77     return Color(col
.Alpha(), col
.Red(), col
.Green(), col
.Blue()); 
  80 } // anonymous namespace 
  82 //----------------------------------------------------------------------------- 
  83 // device context implementation 
  85 // more and more of the dc functionality should be implemented by calling 
  86 // the appropricate wxGDIPlusContext, but we will have to do that step by step 
  87 // also coordinate conversions should be moved to native matrix ops 
  88 //----------------------------------------------------------------------------- 
  90 // we always stock two context states, one at entry, to be able to preserve the 
  91 // state we were called with, the other one after changing to HI Graphics orientation 
  92 // (this one is used for getting back clippings etc) 
  94 //----------------------------------------------------------------------------- 
  95 // wxGraphicsPath implementation 
  96 //----------------------------------------------------------------------------- 
  98 class wxGDIPlusPathData 
: public wxGraphicsPathData
 
 101     wxGDIPlusPathData(wxGraphicsRenderer
* renderer
, GraphicsPath
* path 
= NULL
); 
 102     ~wxGDIPlusPathData(); 
 104     virtual wxGraphicsObjectRefData 
*Clone() const; 
 107     // These are the path primitives from which everything else can be constructed 
 110     // begins a new subpath at (x,y) 
 111     virtual void MoveToPoint( wxDouble x
, wxDouble y 
); 
 113     // adds a straight line from the current point to (x,y) 
 114     virtual void AddLineToPoint( wxDouble x
, wxDouble y 
); 
 116     // adds a cubic Bezier curve from the current point, using two control points and an end point 
 117     virtual void AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y 
); 
 120     // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle 
 121     virtual void AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise 
) ; 
 123     // gets the last point of the current path, (0,0) if not yet set 
 124     virtual void GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const; 
 127     virtual void AddPath( const wxGraphicsPathData
* path 
); 
 129     // closes the current sub-path 
 130     virtual void CloseSubpath(); 
 133     // These are convenience functions which - if not available natively will be assembled 
 134     // using the primitives from above 
 137     // appends a rectangle as a new closed subpath 
 138     virtual void AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) ; 
 141     // appends an ellipsis as a new closed subpath fitting the passed rectangle 
 142     virtual void AddEllipsis( wxDouble x, wxDouble y, wxDouble w , wxDouble h ) ; 
 144     // 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) 
 145     virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )  ; 
 148     // returns the native path 
 149     virtual void * GetNativePath() const { return m_path
; } 
 151     // give the native path returned by GetNativePath() back (there might be some deallocations necessary) 
 152     virtual void UnGetNativePath(void * WXUNUSED(path
)) const {} 
 154     // transforms each point of this path by the matrix 
 155     virtual void Transform( const wxGraphicsMatrixData
* matrix 
) ; 
 157     // gets the bounding box enclosing all points (possibly including control points) 
 158     virtual void GetBox(wxDouble 
*x
, wxDouble 
*y
, wxDouble 
*w
, wxDouble 
*h
) const; 
 160     virtual bool Contains( wxDouble x
, wxDouble y
, wxPolygonFillMode fillStyle 
= wxODDEVEN_RULE
) const; 
 163     GraphicsPath
* m_path
; 
 166 class wxGDIPlusMatrixData 
: public wxGraphicsMatrixData
 
 169     wxGDIPlusMatrixData(wxGraphicsRenderer
* renderer
, Matrix
* matrix 
= NULL
) ; 
 170     virtual ~wxGDIPlusMatrixData() ; 
 172     virtual wxGraphicsObjectRefData
* Clone() const ; 
 174     // concatenates the matrix 
 175     virtual void Concat( const wxGraphicsMatrixData 
*t 
); 
 177     // sets the matrix to the respective values 
 178     virtual void Set(wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0, 
 179         wxDouble tx
=0.0, wxDouble ty
=0.0); 
 181     // gets the component valuess of the matrix 
 182     virtual void Get(wxDouble
* a
=NULL
, wxDouble
* b
=NULL
,  wxDouble
* c
=NULL
, 
 183                      wxDouble
* d
=NULL
, wxDouble
* tx
=NULL
, wxDouble
* ty
=NULL
) const; 
 185     // makes this the inverse matrix 
 186     virtual void Invert(); 
 188     // returns true if the elements of the transformation matrix are equal ? 
 189     virtual bool IsEqual( const wxGraphicsMatrixData
* t
) const ; 
 191     // return true if this is the identity matrix 
 192     virtual bool IsIdentity() const; 
 198     // add the translation to this matrix 
 199     virtual void Translate( wxDouble dx 
, wxDouble dy 
); 
 201     // add the scale to this matrix 
 202     virtual void Scale( wxDouble xScale 
, wxDouble yScale 
); 
 204     // add the rotation to this matrix (radians) 
 205     virtual void Rotate( wxDouble angle 
); 
 208     // apply the transforms 
 211     // applies that matrix to the point 
 212     virtual void TransformPoint( wxDouble 
*x
, wxDouble 
*y 
) const; 
 214     // applies the matrix except for translations 
 215     virtual void TransformDistance( wxDouble 
*dx
, wxDouble 
*dy 
) const; 
 217     // returns the native representation 
 218     virtual void * GetNativeMatrix() const; 
 223 class wxGDIPlusPenData 
: public wxGraphicsObjectRefData
 
 226     wxGDIPlusPenData( wxGraphicsRenderer
* renderer
, const wxPen 
&pen 
); 
 231     virtual wxDouble 
GetWidth() { return m_width
; } 
 232     virtual Pen
* GetGDIPlusPen() { return m_pen
; } 
 242 class wxGDIPlusBrushData 
: public wxGraphicsObjectRefData
 
 245     wxGDIPlusBrushData( wxGraphicsRenderer
* renderer 
); 
 246     wxGDIPlusBrushData( wxGraphicsRenderer
* renderer
, const wxBrush 
&brush 
); 
 247     ~wxGDIPlusBrushData (); 
 249     void CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, 
 250         const wxColour
&c1
, const wxColour
&c2 
); 
 251     void CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
, 
 252         const wxColour 
&oColor
, const wxColour 
&cColor 
); 
 253     virtual Brush
* GetGDIPlusBrush() { return m_brush
; } 
 261     GraphicsPath
* m_brushPath
; 
 264 class WXDLLIMPEXP_CORE wxGDIPlusBitmapData 
: public wxGraphicsObjectRefData
 
 267     wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
, Bitmap
* bitmap 
); 
 268     wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
, const wxBitmap 
&bmp 
); 
 269     ~wxGDIPlusBitmapData (); 
 271     virtual Bitmap
* GetGDIPlusBitmap() { return m_bitmap
; } 
 278 class wxGDIPlusFontData 
: public wxGraphicsObjectRefData
 
 281     wxGDIPlusFontData( wxGraphicsRenderer
* renderer
, const wxFont 
&font
, const wxColour
& col 
); 
 282     ~wxGDIPlusFontData(); 
 284     virtual Brush
* GetGDIPlusBrush() { return m_textBrush
; } 
 285     virtual Font
* GetGDIPlusFont() { return m_font
; } 
 291 class wxGDIPlusContext 
: public wxGraphicsContext
 
 294     wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HDC hdc 
, wxDouble width
, wxDouble height 
); 
 295     wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HWND hwnd 
); 
 296     wxGDIPlusContext( wxGraphicsRenderer
* renderer
, Graphics
* gr
); 
 299     virtual ~wxGDIPlusContext(); 
 301     virtual void Clip( const wxRegion 
®ion 
); 
 302     // clips drawings to the rect 
 303     virtual void Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
); 
 305     // resets the clipping to original extent 
 306     virtual void ResetClip(); 
 308     virtual void * GetNativeContext(); 
 310     virtual void StrokePath( const wxGraphicsPath
& p 
); 
 311     virtual void FillPath( const wxGraphicsPath
& p 
, wxPolygonFillMode fillStyle 
= wxODDEVEN_RULE 
); 
 313     // stroke lines connecting each of the points 
 314     virtual void StrokeLines( size_t n
, const wxPoint2DDouble 
*points
); 
 317     virtual void DrawLines( size_t n
, const wxPoint2DDouble 
*points
, wxPolygonFillMode fillStyle 
= wxODDEVEN_RULE 
); 
 319     virtual bool SetAntialiasMode(wxAntialiasMode antialias
); 
 321     virtual bool SetCompositionMode(wxCompositionMode op
); 
 323     virtual void BeginLayer(wxDouble opacity
); 
 325     virtual void EndLayer(); 
 327     virtual void Translate( wxDouble dx 
, wxDouble dy 
); 
 328     virtual void Scale( wxDouble xScale 
, wxDouble yScale 
); 
 329     virtual void Rotate( wxDouble angle 
); 
 331     // concatenates this transform with the current transform of this context 
 332     virtual void ConcatTransform( const wxGraphicsMatrix
& matrix 
); 
 334     // sets the transform of this context 
 335     virtual void SetTransform( const wxGraphicsMatrix
& matrix 
); 
 337     // gets the matrix of this context 
 338     virtual wxGraphicsMatrix 
GetTransform() const; 
 340     virtual void DrawBitmap( const wxGraphicsBitmap 
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
); 
 341     virtual void DrawBitmap( const wxBitmap 
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
); 
 342     virtual void DrawIcon( const wxIcon 
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
); 
 343     virtual void PushState(); 
 344     virtual void PopState(); 
 346     virtual void GetTextExtent( const wxString 
&str
, wxDouble 
*width
, wxDouble 
*height
, 
 347         wxDouble 
*descent
, wxDouble 
*externalLeading 
) const; 
 348     virtual void GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const; 
 349     virtual bool ShouldOffset() const; 
 350     virtual void GetSize( wxDouble
* width
, wxDouble 
*height 
); 
 356     virtual void DoDrawText(const wxString
& str
, wxDouble x
, wxDouble y
) 
 357         { DoDrawFilledText(str
, x
, y
, wxNullGraphicsBrush
); } 
 358     virtual void DoDrawFilledText(const wxString
& str
, wxDouble x
, wxDouble y
, 
 359                                   const wxGraphicsBrush
& backgroundBrush
); 
 362     GraphicsStates m_stateStack
; 
 363     GraphicsState m_state1
; 
 364     GraphicsState m_state2
; 
 369     DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusContext
) 
 372 class wxGDIPlusMeasuringContext 
: public wxGDIPlusContext
 
 375     wxGDIPlusMeasuringContext( wxGraphicsRenderer
* renderer 
) : wxGDIPlusContext( renderer 
, m_hdc 
= GetDC(NULL
), 1000, 1000 ) 
 378     wxGDIPlusMeasuringContext() 
 382     virtual ~wxGDIPlusMeasuringContext() 
 384         ReleaseDC( NULL
, m_hdc 
); 
 389     DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusMeasuringContext
) 
 392 //----------------------------------------------------------------------------- 
 393 // wxGDIPlusPen implementation 
 394 //----------------------------------------------------------------------------- 
 396 wxGDIPlusPenData::~wxGDIPlusPenData() 
 403 void wxGDIPlusPenData::Init() 
 410 wxGDIPlusPenData::wxGDIPlusPenData( wxGraphicsRenderer
* renderer
, const wxPen 
&pen 
) 
 411 : wxGraphicsObjectRefData(renderer
) 
 414     m_width 
= pen
.GetWidth(); 
 418     m_pen 
= new Pen(wxColourToColor(pen
.GetColour()), m_width 
); 
 421     switch ( pen
.GetCap() ) 
 427     case wxCAP_PROJECTING 
: 
 432         cap 
= LineCapFlat
; // TODO verify 
 439     m_pen
->SetLineCap(cap
,cap
, DashCapFlat
); 
 442     switch ( pen
.GetJoin() ) 
 445         join 
= LineJoinBevel
; 
 449         join 
= LineJoinMiter
; 
 453         join 
= LineJoinRound
; 
 457         join 
= LineJoinMiter
; 
 461     m_pen
->SetLineJoin(join
); 
 463     m_pen
->SetDashStyle(DashStyleSolid
); 
 465     DashStyle dashStyle 
= DashStyleSolid
; 
 466     switch ( pen
.GetStyle() ) 
 472         dashStyle 
= DashStyleDot
; 
 476         dashStyle 
= DashStyleDash
; // TODO verify 
 480         dashStyle 
= DashStyleDash
; 
 484         dashStyle 
= DashStyleDashDot
; 
 488             dashStyle 
= DashStyleCustom
; 
 490             int count 
= pen
.GetDashes( &dashes 
); 
 491             if ((dashes 
!= NULL
) && (count 
> 0)) 
 493                 REAL 
*userLengths 
= new REAL
[count
]; 
 494                 for ( int i 
= 0; i 
< count
; ++i 
) 
 496                     userLengths
[i
] = dashes
[i
]; 
 498                 m_pen
->SetDashPattern( userLengths
, count
); 
 499                 delete[] userLengths
; 
 505             wxBitmap
* bmp 
= pen
.GetStipple(); 
 506             if ( bmp 
&& bmp
->Ok() ) 
 508                 m_penImage 
= Bitmap::FromHBITMAP((HBITMAP
)bmp
->GetHBITMAP(),(HPALETTE
)bmp
->GetPalette()->GetHPALETTE()); 
 509                 m_penBrush 
= new TextureBrush(m_penImage
); 
 510                 m_pen
->SetBrush( m_penBrush 
); 
 516         if ( pen
.GetStyle() >= wxFIRST_HATCH 
&& pen
.GetStyle() <= wxLAST_HATCH 
) 
 518             HatchStyle style 
= HatchStyleHorizontal
; 
 519             switch( pen
.GetStyle() ) 
 521             case wxBDIAGONAL_HATCH 
: 
 522                 style 
= HatchStyleBackwardDiagonal
; 
 524             case wxCROSSDIAG_HATCH 
: 
 525                 style 
= HatchStyleDiagonalCross
; 
 527             case wxFDIAGONAL_HATCH 
: 
 528                 style 
= HatchStyleForwardDiagonal
; 
 531                 style 
= HatchStyleCross
; 
 533             case wxHORIZONTAL_HATCH 
: 
 534                 style 
= HatchStyleHorizontal
; 
 536             case wxVERTICAL_HATCH 
: 
 537                 style 
= HatchStyleVertical
; 
 541             m_penBrush 
= new HatchBrush
 
 544                                 wxColourToColor(pen
.GetColour()), 
 547             m_pen
->SetBrush( m_penBrush 
); 
 551     if ( dashStyle 
!= DashStyleSolid 
) 
 552         m_pen
->SetDashStyle(dashStyle
); 
 555 //----------------------------------------------------------------------------- 
 556 // wxGDIPlusBrush implementation 
 557 //----------------------------------------------------------------------------- 
 559 wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer
* renderer 
) 
 560 : wxGraphicsObjectRefData(renderer
) 
 565 wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer
* renderer 
, const wxBrush 
&brush 
) 
 566 : wxGraphicsObjectRefData(renderer
) 
 569     if ( brush
.GetStyle() == wxSOLID
) 
 571         m_brush 
= new SolidBrush(wxColourToColor( brush
.GetColour())); 
 573     else if ( brush
.IsHatch() ) 
 575         HatchStyle style 
= HatchStyleHorizontal
; 
 576         switch( brush
.GetStyle() ) 
 578         case wxBDIAGONAL_HATCH 
: 
 579             style 
= HatchStyleBackwardDiagonal
; 
 581         case wxCROSSDIAG_HATCH 
: 
 582             style 
= HatchStyleDiagonalCross
; 
 584         case wxFDIAGONAL_HATCH 
: 
 585             style 
= HatchStyleForwardDiagonal
; 
 588             style 
= HatchStyleCross
; 
 590         case wxHORIZONTAL_HATCH 
: 
 591             style 
= HatchStyleHorizontal
; 
 593         case wxVERTICAL_HATCH 
: 
 594             style 
= HatchStyleVertical
; 
 598         m_brush 
= new HatchBrush
 
 601                         wxColourToColor(brush
.GetColour()), 
 607         wxBitmap
* bmp 
= brush
.GetStipple(); 
 608         if ( bmp 
&& bmp
->Ok() ) 
 610             wxDELETE( m_brushImage 
); 
 611             m_brushImage 
= Bitmap::FromHBITMAP((HBITMAP
)bmp
->GetHBITMAP(),(HPALETTE
)bmp
->GetPalette()->GetHPALETTE()); 
 612             m_brush 
= new TextureBrush(m_brushImage
); 
 617 wxGDIPlusBrushData::~wxGDIPlusBrushData() 
 624 void wxGDIPlusBrushData::Init() 
 631 void wxGDIPlusBrushData::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, const wxColour
&c1
, const wxColour
&c2
) 
 633     m_brush 
= new LinearGradientBrush( PointF( x1
,y1
) , PointF( x2
,y2
), 
 634         Color( c1
.Alpha(), c1
.Red(),c1
.Green() , c1
.Blue() ), 
 635         Color( c2
.Alpha(), c2
.Red(),c2
.Green() , c2
.Blue() )); 
 638 void wxGDIPlusBrushData::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
, 
 639                                                const wxColour 
&oColor
, const wxColour 
&cColor
) 
 641     // Create a path that consists of a single circle. 
 642     m_brushPath 
= new GraphicsPath(); 
 643     m_brushPath
->AddEllipse( (REAL
)(xc
-radius
), (REAL
)(yc
-radius
), (REAL
)(2*radius
), (REAL
)(2*radius
)); 
 645     PathGradientBrush 
*b 
= new PathGradientBrush(m_brushPath
); 
 647     b
->SetCenterPoint( PointF(xo
,yo
)); 
 648     b
->SetCenterColor(Color( oColor
.Alpha(), oColor
.Red(),oColor
.Green() , oColor
.Blue() )); 
 650     Color colors
[] = {Color( cColor
.Alpha(), cColor
.Red(),cColor
.Green() , cColor
.Blue() )}; 
 652     b
->SetSurroundColors(colors
, &count
); 
 655 //----------------------------------------------------------------------------- 
 656 // wxGDIPlusFont implementation 
 657 //----------------------------------------------------------------------------- 
 659 wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer
* renderer
, const wxFont 
&font
, 
 660                              const wxColour
& col 
) : wxGraphicsObjectRefData( renderer 
) 
 665     wxWCharBuffer s 
= font
.GetFaceName().wc_str( *wxConvUI 
); 
 666     int size 
= font
.GetPointSize(); 
 667     int style 
= FontStyleRegular
; 
 668     if ( font
.GetStyle() == wxFONTSTYLE_ITALIC 
) 
 669         style 
|= FontStyleItalic
; 
 670     if ( font
.GetUnderlined() ) 
 671         style 
|= FontStyleUnderline
; 
 672     if ( font
.GetWeight() == wxFONTWEIGHT_BOLD 
) 
 673         style 
|= FontStyleBold
; 
 674     m_font 
= new Font( s 
, size 
, style 
); 
 675     m_textBrush 
= new SolidBrush(wxColourToColor(col
)); 
 678 wxGDIPlusFontData::~wxGDIPlusFontData() 
 684 // the built-in conversions functions create non-premultiplied bitmaps, while GDIPlus needs them in the 
 685 // premultiplied format, therefore in the failing cases we create a new bitmap using the non-premultiplied 
 686 // bytes as parameter, since there is no real copying of the data going in, only references are stored 
 687 // m_helper has to be kept alive as well 
 689 //----------------------------------------------------------------------------- 
 690 // wxGDIPlusBitmapData implementation 
 691 //----------------------------------------------------------------------------- 
 693 wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
, Bitmap
* bitmap 
) : 
 694     wxGraphicsObjectRefData( renderer 
), m_bitmap( bitmap 
) 
 699 wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
, 
 700                         const wxBitmap 
&bmp
) : wxGraphicsObjectRefData( renderer 
) 
 705     Bitmap
* image 
= NULL
; 
 708         Bitmap 
interim((HBITMAP
)bmp
.GetHBITMAP(),(HPALETTE
)bmp
.GetPalette()->GetHPALETTE()) ; 
 710         size_t width 
= interim
.GetWidth(); 
 711         size_t height 
= interim
.GetHeight(); 
 712         Rect 
bounds(0,0,width
,height
); 
 714         image 
= new Bitmap(width
,height
,PixelFormat32bppPARGB
) ; 
 716         Bitmap 
interimMask((HBITMAP
)bmp
.GetMask()->GetMaskBitmap(),NULL
); 
 717         wxASSERT(interimMask
.GetPixelFormat() == PixelFormat1bppIndexed
); 
 719         BitmapData dataMask 
; 
 720         interimMask
.LockBits(&bounds
,ImageLockModeRead
, 
 721             interimMask
.GetPixelFormat(),&dataMask
); 
 724         BitmapData imageData 
; 
 725         image
->LockBits(&bounds
,ImageLockModeWrite
, PixelFormat32bppPARGB
, &imageData
); 
 727         BYTE maskPattern 
= 0 ; 
 731         for ( size_t y 
= 0 ; y 
< height 
; ++y
) 
 734             for( size_t x 
= 0 ; x 
< width
; ++x
) 
 739                     maskByte 
= *((BYTE
*)dataMask
.Scan0 
+ dataMask
.Stride
*y 
+ maskIndex
); 
 743                     maskPattern 
= maskPattern 
>> 1; 
 745                 ARGB 
*dest 
= (ARGB
*)((BYTE
*)imageData
.Scan0 
+ imageData
.Stride
*y 
+ x
*4); 
 746                 if ( (maskByte 
& maskPattern
) == 0 ) 
 751                     interim
.GetPixel(x
,y
,&c
) ; 
 752                     *dest 
= (c
.GetValue() | Color::AlphaMask
); 
 757         image
->UnlockBits(&imageData
); 
 759         interimMask
.UnlockBits(&dataMask
); 
 760         interim
.UnlockBits(&dataMask
); 
 764         image 
= Bitmap::FromHBITMAP((HBITMAP
)bmp
.GetHBITMAP(),(HPALETTE
)bmp
.GetPalette()->GetHPALETTE()); 
 765         if ( bmp
.HasAlpha() && GetPixelFormatSize(image
->GetPixelFormat()) == 32 ) 
 767             size_t width 
= image
->GetWidth(); 
 768             size_t height 
= image
->GetHeight(); 
 769             Rect 
bounds(0,0,width
,height
); 
 770             static BitmapData data 
; 
 774             m_helper
->LockBits(&bounds
, ImageLockModeRead
, 
 775                 m_helper
->GetPixelFormat(),&data
); 
 777             image 
= new Bitmap(data
.Width
, data
.Height
, data
.Stride
, 
 778                 PixelFormat32bppPARGB 
, (BYTE
*) data
.Scan0
); 
 780             m_helper
->UnlockBits(&data
); 
 787 wxGDIPlusBitmapData::~wxGDIPlusBitmapData() 
 793 //----------------------------------------------------------------------------- 
 794 // wxGDIPlusPath implementation 
 795 //----------------------------------------------------------------------------- 
 797 wxGDIPlusPathData::wxGDIPlusPathData(wxGraphicsRenderer
* renderer
, GraphicsPath
* path 
) : wxGraphicsPathData(renderer
) 
 802         m_path 
= new GraphicsPath(); 
 805 wxGDIPlusPathData::~wxGDIPlusPathData() 
 810 wxGraphicsObjectRefData
* wxGDIPlusPathData::Clone() const 
 812     return new wxGDIPlusPathData( GetRenderer() , m_path
->Clone()); 
 819 void wxGDIPlusPathData::MoveToPoint( wxDouble x 
, wxDouble y 
) 
 821     m_path
->StartFigure(); 
 822     m_path
->AddLine((REAL
) x
,(REAL
) y
,(REAL
) x
,(REAL
) y
); 
 825 void wxGDIPlusPathData::AddLineToPoint( wxDouble x 
, wxDouble y 
) 
 827     m_path
->AddLine((REAL
) x
,(REAL
) y
,(REAL
) x
,(REAL
) y
); 
 830 void wxGDIPlusPathData::CloseSubpath() 
 832     m_path
->CloseFigure(); 
 835 void wxGDIPlusPathData::AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y 
) 
 841     m_path
->GetLastPoint(&start
); 
 842     m_path
->AddBezier(start
,c1
,c2
,end
); 
 845 // gets the last point of the current path, (0,0) if not yet set 
 846 void wxGDIPlusPathData::GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const 
 849     m_path
->GetLastPoint(&start
); 
 854 void wxGDIPlusPathData::AddArc( wxDouble x
, wxDouble y
, wxDouble r
, double startAngle
, double endAngle
, bool clockwise 
) 
 856     double sweepAngle 
= endAngle 
- startAngle 
; 
 857     if( fabs(sweepAngle
) >= 2*M_PI
) 
 859         sweepAngle 
= 2 * M_PI
; 
 866                 sweepAngle 
+= 2 * M_PI
; 
 871                 sweepAngle 
-= 2 * M_PI
; 
 875    m_path
->AddArc((REAL
) (x
-r
),(REAL
) (y
-r
),(REAL
) (2*r
),(REAL
) (2*r
),RadToDeg(startAngle
),RadToDeg(sweepAngle
)); 
 878 void wxGDIPlusPathData::AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
 880     m_path
->AddRectangle(RectF(x
,y
,w
,h
)); 
 883 void wxGDIPlusPathData::AddPath( const wxGraphicsPathData
* path 
) 
 885     m_path
->AddPath( (GraphicsPath
*) path
->GetNativePath(), FALSE
); 
 889 // transforms each point of this path by the matrix 
 890 void wxGDIPlusPathData::Transform( const wxGraphicsMatrixData
* matrix 
) 
 892     m_path
->Transform( (Matrix
*) matrix
->GetNativeMatrix() ); 
 895 // gets the bounding box enclosing all points (possibly including control points) 
 896 void wxGDIPlusPathData::GetBox(wxDouble 
*x
, wxDouble 
*y
, wxDouble 
*w
, wxDouble 
*h
) const 
 899     m_path
->GetBounds( &bounds
, NULL
, NULL
) ; 
 906 bool wxGDIPlusPathData::Contains( wxDouble x
, wxDouble y
, wxPolygonFillMode fillStyle 
) const 
 908     m_path
->SetFillMode( fillStyle 
== wxODDEVEN_RULE 
? FillModeAlternate 
: FillModeWinding
); 
 909     return m_path
->IsVisible( (FLOAT
) x
,(FLOAT
) y
) == TRUE 
; 
 912 //----------------------------------------------------------------------------- 
 913 // wxGDIPlusMatrixData implementation 
 914 //----------------------------------------------------------------------------- 
 916 wxGDIPlusMatrixData::wxGDIPlusMatrixData(wxGraphicsRenderer
* renderer
, Matrix
* matrix 
) 
 917     : wxGraphicsMatrixData(renderer
) 
 922         m_matrix 
= new Matrix(); 
 925 wxGDIPlusMatrixData::~wxGDIPlusMatrixData() 
 930 wxGraphicsObjectRefData 
*wxGDIPlusMatrixData::Clone() const 
 932     return new wxGDIPlusMatrixData( GetRenderer(), m_matrix
->Clone()); 
 935 // concatenates the matrix 
 936 void wxGDIPlusMatrixData::Concat( const wxGraphicsMatrixData 
*t 
) 
 938     m_matrix
->Multiply( (Matrix
*) t
->GetNativeMatrix()); 
 941 // sets the matrix to the respective values 
 942 void wxGDIPlusMatrixData::Set(wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
, 
 943                  wxDouble tx
, wxDouble ty
) 
 945     m_matrix
->SetElements(a
,b
,c
,d
,tx
,ty
); 
 948 // gets the component valuess of the matrix 
 949 void wxGDIPlusMatrixData::Get(wxDouble
* a
, wxDouble
* b
,  wxDouble
* c
, 
 950                               wxDouble
* d
, wxDouble
* tx
, wxDouble
* ty
) const 
 953     m_matrix
->GetElements(elements
); 
 954     if (a
)  *a 
= elements
[0]; 
 955     if (b
)  *b 
= elements
[1]; 
 956     if (c
)  *c 
= elements
[2]; 
 957     if (d
)  *d 
= elements
[3]; 
 958     if (tx
) *tx
= elements
[4]; 
 959     if (ty
) *ty
= elements
[5]; 
 962 // makes this the inverse matrix 
 963 void wxGDIPlusMatrixData::Invert() 
 968 // returns true if the elements of the transformation matrix are equal ? 
 969 bool wxGDIPlusMatrixData::IsEqual( const wxGraphicsMatrixData
* t
) const 
 971     return m_matrix
->Equals((Matrix
*) t
->GetNativeMatrix())== TRUE 
; 
 974 // return true if this is the identity matrix 
 975 bool wxGDIPlusMatrixData::IsIdentity() const 
 977     return m_matrix
->IsIdentity() == TRUE 
; 
 984 // add the translation to this matrix 
 985 void wxGDIPlusMatrixData::Translate( wxDouble dx 
, wxDouble dy 
) 
 987     m_matrix
->Translate(dx
,dy
); 
 990 // add the scale to this matrix 
 991 void wxGDIPlusMatrixData::Scale( wxDouble xScale 
, wxDouble yScale 
) 
 993     m_matrix
->Scale(xScale
,yScale
); 
 996 // add the rotation to this matrix (radians) 
 997 void wxGDIPlusMatrixData::Rotate( wxDouble angle 
) 
 999     m_matrix
->Rotate( angle 
); 
1003 // apply the transforms 
1006 // applies that matrix to the point 
1007 void wxGDIPlusMatrixData::TransformPoint( wxDouble 
*x
, wxDouble 
*y 
) const 
1010     m_matrix
->TransformPoints(&pt
); 
1015 // applies the matrix except for translations 
1016 void wxGDIPlusMatrixData::TransformDistance( wxDouble 
*dx
, wxDouble 
*dy 
) const 
1019     m_matrix
->TransformVectors(&pt
); 
1024 // returns the native representation 
1025 void * wxGDIPlusMatrixData::GetNativeMatrix() const 
1030 //----------------------------------------------------------------------------- 
1031 // wxGDIPlusContext implementation 
1032 //----------------------------------------------------------------------------- 
1034 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusContext
,wxGraphicsContext
) 
1035 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusMeasuringContext
,wxGDIPlusContext
) 
1037 class wxGDIPlusOffsetHelper
 
1040     wxGDIPlusOffsetHelper( Graphics
* gr 
, bool offset 
) 
1045             m_gr
->TranslateTransform( 0.5, 0.5 ); 
1047     ~wxGDIPlusOffsetHelper( ) 
1050             m_gr
->TranslateTransform( -0.5, -0.5 ); 
1057 wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HDC hdc
, wxDouble width
, wxDouble height   
) 
1058     : wxGraphicsContext(renderer
) 
1061     m_context 
= new Graphics( hdc
); 
1067 wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HWND hwnd  
) 
1068     : wxGraphicsContext(renderer
) 
1071     m_context 
= new Graphics( hwnd
); 
1072     RECT rect 
= wxGetWindowRect(hwnd
); 
1073     m_width 
= rect
.right 
- rect
.left
; 
1074     m_height 
= rect
.bottom 
- rect
.top
; 
1078 wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer
* renderer
, Graphics
* gr  
) 
1079     : wxGraphicsContext(renderer
) 
1086 wxGDIPlusContext::wxGDIPlusContext() : wxGraphicsContext(NULL
) 
1091 void wxGDIPlusContext::Init() 
1100 void wxGDIPlusContext::SetDefaults() 
1102     m_context
->SetTextRenderingHint(TextRenderingHintSystemDefault
); 
1103     m_context
->SetPixelOffsetMode(PixelOffsetModeHalf
); 
1104     m_context
->SetSmoothingMode(SmoothingModeHighQuality
); 
1105     m_state1 
= m_context
->Save(); 
1106     m_state2 
= m_context
->Save(); 
1109 wxGDIPlusContext::~wxGDIPlusContext() 
1113         m_context
->Restore( m_state2 
); 
1114         m_context
->Restore( m_state1 
); 
1120 void wxGDIPlusContext::Clip( const wxRegion 
®ion 
) 
1122     Region 
rgn((HRGN
)region
.GetHRGN()); 
1123     m_context
->SetClip(&rgn
,CombineModeIntersect
); 
1126 void wxGDIPlusContext::Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
1128     m_context
->SetClip(RectF(x
,y
,w
,h
),CombineModeIntersect
); 
1131 void wxGDIPlusContext::ResetClip() 
1133     m_context
->ResetClip(); 
1136 void wxGDIPlusContext::StrokeLines( size_t n
, const wxPoint2DDouble 
*points
) 
1138    if (m_composition 
== wxCOMPOSITION_DEST
) 
1141    if ( !m_pen
.IsNull() ) 
1143        wxGDIPlusOffsetHelper 
helper( m_context 
, ShouldOffset() ); 
1144        Point 
*cpoints 
= new Point
[n
]; 
1145        for (size_t i 
= 0; i 
< n
; i
++) 
1147            cpoints
[i
].X 
= (int)(points
[i
].m_x 
); 
1148            cpoints
[i
].Y 
= (int)(points
[i
].m_y 
); 
1150        } // for (size_t i = 0; i < n; i++) 
1151        m_context
->DrawLines( ((wxGDIPlusPenData
*)m_pen
.GetGraphicsData())->GetGDIPlusPen() , cpoints 
, n 
) ; 
1156 void wxGDIPlusContext::DrawLines( size_t n
, const wxPoint2DDouble 
*points
, wxPolygonFillMode 
WXUNUSED(fillStyle
) ) 
1158    if (m_composition 
== wxCOMPOSITION_DEST
) 
1161     wxGDIPlusOffsetHelper 
helper( m_context 
, ShouldOffset() ); 
1162     Point 
*cpoints 
= new Point
[n
]; 
1163     for (size_t i 
= 0; i 
< n
; i
++) 
1165         cpoints
[i
].X 
= (int)(points
[i
].m_x 
); 
1166         cpoints
[i
].Y 
= (int)(points
[i
].m_y 
); 
1168     } // for (int i = 0; i < n; i++) 
1169     if ( !m_brush
.IsNull() ) 
1170         m_context
->FillPolygon( ((wxGDIPlusBrushData
*)m_brush
.GetRefData())->GetGDIPlusBrush() , cpoints 
, n 
) ; 
1171     if ( !m_pen
.IsNull() ) 
1172         m_context
->DrawLines( ((wxGDIPlusPenData
*)m_pen
.GetGraphicsData())->GetGDIPlusPen() , cpoints 
, n 
) ; 
1176 void wxGDIPlusContext::StrokePath( const wxGraphicsPath
& path 
) 
1178    if (m_composition 
== wxCOMPOSITION_DEST
) 
1181     if ( !m_pen
.IsNull() ) 
1183         wxGDIPlusOffsetHelper 
helper( m_context 
, ShouldOffset() ); 
1184         m_context
->DrawPath( ((wxGDIPlusPenData
*)m_pen
.GetGraphicsData())->GetGDIPlusPen() , (GraphicsPath
*) path
.GetNativePath() ); 
1188 void wxGDIPlusContext::FillPath( const wxGraphicsPath
& path 
, wxPolygonFillMode fillStyle 
) 
1190    if (m_composition 
== wxCOMPOSITION_DEST
) 
1193     if ( !m_brush
.IsNull() ) 
1195         wxGDIPlusOffsetHelper 
helper( m_context 
, ShouldOffset() ); 
1196         ((GraphicsPath
*) path
.GetNativePath())->SetFillMode( fillStyle 
== wxODDEVEN_RULE 
? FillModeAlternate 
: FillModeWinding
); 
1197         m_context
->FillPath( ((wxGDIPlusBrushData
*)m_brush
.GetRefData())->GetGDIPlusBrush() , 
1198             (GraphicsPath
*) path
.GetNativePath()); 
1202 bool wxGDIPlusContext::SetAntialiasMode(wxAntialiasMode antialias
) 
1204     if (m_antialias 
== antialias
) 
1207     m_antialias 
= antialias
; 
1209     SmoothingMode antialiasMode
; 
1212         case wxANTIALIAS_DEFAULT
: 
1213             antialiasMode 
= SmoothingModeHighQuality
; 
1215         case wxANTIALIAS_NONE
: 
1216             antialiasMode 
= SmoothingModeNone
; 
1221     m_context
->SetSmoothingMode(antialiasMode
); 
1225 bool wxGDIPlusContext::SetCompositionMode(wxCompositionMode op
) 
1227     if ( m_composition 
== op 
) 
1232     if (m_composition 
== wxCOMPOSITION_DEST
) 
1235     CompositingMode cop
; 
1238         case wxCOMPOSITION_SOURCE
: 
1239             cop 
= CompositingModeSourceCopy
; 
1241         case wxCOMPOSITION_OVER
: 
1242             cop 
= CompositingModeSourceOver
; 
1248     m_context
->SetCompositingMode(cop
); 
1252 void wxGDIPlusContext::BeginLayer(wxDouble 
/* opacity */) 
1257 void wxGDIPlusContext::EndLayer() 
1262 void wxGDIPlusContext::Rotate( wxDouble angle 
) 
1264     m_context
->RotateTransform( RadToDeg(angle
) ); 
1267 void wxGDIPlusContext::Translate( wxDouble dx 
, wxDouble dy 
) 
1269     m_context
->TranslateTransform( dx 
, dy 
); 
1272 void wxGDIPlusContext::Scale( wxDouble xScale 
, wxDouble yScale 
) 
1274     m_context
->ScaleTransform(xScale
,yScale
); 
1277 void wxGDIPlusContext::PushState() 
1279     GraphicsState state 
= m_context
->Save(); 
1280     m_stateStack
.push(state
); 
1283 void wxGDIPlusContext::PopState() 
1285     GraphicsState state 
= m_stateStack
.top(); 
1287     m_context
->Restore(state
); 
1290 void wxGDIPlusContext::DrawBitmap( const wxGraphicsBitmap 
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
1292    if (m_composition 
== wxCOMPOSITION_DEST
) 
1295     Bitmap
* image 
= static_cast<wxGDIPlusBitmapData
*>(bmp
.GetRefData())->GetGDIPlusBitmap(); 
1298         if( image
->GetWidth() != (UINT
) w 
|| image
->GetHeight() != (UINT
) h 
) 
1300             Rect 
drawRect((REAL
) x
, (REAL
)y
, (REAL
)w
, (REAL
)h
); 
1301             m_context
->SetPixelOffsetMode( PixelOffsetModeNone 
); 
1302             m_context
->DrawImage(image
, drawRect
, 0 , 0 , image
->GetWidth()-1, image
->GetHeight()-1, UnitPixel 
) ; 
1303             m_context
->SetPixelOffsetMode( PixelOffsetModeHalf 
); 
1306             m_context
->DrawImage(image
,(REAL
) x
,(REAL
) y
,(REAL
) w
,(REAL
) h
) ; 
1310 void wxGDIPlusContext::DrawBitmap( const wxBitmap 
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
1312     wxGraphicsBitmap bitmap 
= GetRenderer()->CreateBitmap(bmp
); 
1313     DrawBitmap(bitmap
, x
, y
, w
, h
); 
1316 void wxGDIPlusContext::DrawIcon( const wxIcon 
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h 
) 
1318    if (m_composition 
== wxCOMPOSITION_DEST
) 
1321     // the built-in conversion fails when there is alpha in the HICON (eg XP style icons), we can only 
1322     // find out by looking at the bitmap data whether there really was alpha in it 
1323     HICON hIcon 
= (HICON
)icon
.GetHICON(); 
1325     // IconInfo creates the bitmaps for color and mask, we must dispose of them after use 
1326     if (!GetIconInfo(hIcon
,&iconInfo
)) 
1329     Bitmap 
interim(iconInfo
.hbmColor
,NULL
); 
1331     Bitmap
* image 
= NULL 
; 
1333     // if it's not 32 bit, it doesn't have an alpha channel, note that since the conversion doesn't 
1334     // work correctly, asking IsAlphaPixelFormat at this point fails as well 
1335     if( GetPixelFormatSize(interim
.GetPixelFormat())!= 32 ) 
1337         image 
= Bitmap::FromHICON(hIcon
); 
1341         size_t width 
= interim
.GetWidth(); 
1342         size_t height 
= interim
.GetHeight(); 
1343         Rect 
bounds(0,0,width
,height
); 
1346         interim
.LockBits(&bounds
, ImageLockModeRead
, 
1347             interim
.GetPixelFormat(),&data
); 
1349         bool hasAlpha 
= false; 
1350         for ( size_t y 
= 0 ; y 
< height 
&& !hasAlpha 
; ++y
) 
1352             for( size_t x 
= 0 ; x 
< width 
&& !hasAlpha
; ++x
) 
1354                 ARGB 
*dest 
= (ARGB
*)((BYTE
*)data
.Scan0 
+ data
.Stride
*y 
+ x
*4); 
1355                 if ( ( *dest 
& Color::AlphaMask 
) != 0 ) 
1362         image 
= new Bitmap(data
.Width
, data
.Height
, data
.Stride
, 
1363             PixelFormat32bppARGB 
, (BYTE
*) data
.Scan0
); 
1367             image 
= Bitmap::FromHICON(hIcon
); 
1370         interim
.UnlockBits(&data
); 
1373     m_context
->DrawImage(image
,(REAL
) x
,(REAL
) y
,(REAL
) w
,(REAL
) h
) ; 
1376     DeleteObject(iconInfo
.hbmColor
); 
1377     DeleteObject(iconInfo
.hbmMask
); 
1380 void wxGDIPlusContext::DoDrawFilledText(const wxString
& str
, 
1381                                         wxDouble x
, wxDouble y
, 
1382                                         const wxGraphicsBrush
& brush
) 
1384    if (m_composition 
== wxCOMPOSITION_DEST
) 
1387     wxCHECK_RET( !m_font
.IsNull(), 
1388                  wxT("wxGDIPlusContext::DrawText - no valid font set") ); 
1393     wxGDIPlusFontData 
* const 
1394         fontData 
= (wxGDIPlusFontData 
*)m_font
.GetRefData(); 
1395     wxGDIPlusBrushData 
* const 
1396         brushData 
= (wxGDIPlusBrushData 
*)brush
.GetRefData(); 
1398     m_context
->DrawString
 
1400                     str
.wc_str(*wxConvUI
),  // string to draw, always Unicode 
1401                     -1,                     // length: string is NUL-terminated 
1402                     fontData
->GetGDIPlusFont(), 
1404                     StringFormat::GenericTypographic(), 
1405                     brushData 
? brushData
->GetGDIPlusBrush() 
1406                               : fontData
->GetGDIPlusBrush() 
1410 void wxGDIPlusContext::GetTextExtent( const wxString 
&str
, wxDouble 
*width
, wxDouble 
*height
, 
1411                                      wxDouble 
*descent
, wxDouble 
*externalLeading 
) const 
1413     wxCHECK_RET( !m_font
.IsNull(), wxT("wxGDIPlusContext::GetTextExtent - no valid font set") ); 
1415     wxWCharBuffer s 
= str
.wc_str( *wxConvUI 
); 
1416     FontFamily ffamily 
; 
1417     Font
* f 
= ((wxGDIPlusFontData
*)m_font
.GetRefData())->GetGDIPlusFont(); 
1419     f
->GetFamily(&ffamily
) ; 
1421     REAL factorY 
= m_context
->GetDpiY() / 72.0 ; 
1423     REAL rDescent 
= ffamily
.GetCellDescent(FontStyleRegular
) * 
1424         f
->GetSize() / ffamily
.GetEmHeight(FontStyleRegular
); 
1425     REAL rAscent 
= ffamily
.GetCellAscent(FontStyleRegular
) * 
1426         f
->GetSize() / ffamily
.GetEmHeight(FontStyleRegular
); 
1427     REAL rHeight 
= ffamily
.GetLineSpacing(FontStyleRegular
) * 
1428         f
->GetSize() / ffamily
.GetEmHeight(FontStyleRegular
); 
1431         *height 
= rHeight 
* factorY
; 
1433         *descent 
= rDescent 
* factorY
; 
1434     if ( externalLeading 
) 
1435         *externalLeading 
= (rHeight 
- rAscent 
- rDescent
) * factorY
; 
1436     // measuring empty strings is not guaranteed, so do it by hand 
1444         RectF 
layoutRect(0,0, 100000.0f
, 100000.0f
); 
1445         StringFormat 
strFormat( StringFormat::GenericTypographic() ); 
1446         strFormat
.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces 
| strFormat
.GetFormatFlags() ); 
1449         m_context
->MeasureString((const wchar_t *) s 
, wcslen(s
) , f
, layoutRect
, &strFormat
, &bounds 
) ; 
1451             *width 
= bounds
.Width
; 
1455 void wxGDIPlusContext::GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const 
1458     widths
.Add(0, text
.length()); 
1460     wxCHECK_RET( !m_font
.IsNull(), wxT("wxGDIPlusContext::GetPartialTextExtents - no valid font set") ); 
1465     Font
* f 
= ((wxGDIPlusFontData
*)m_font
.GetRefData())->GetGDIPlusFont(); 
1466     wxWCharBuffer ws 
= text
.wc_str( *wxConvUI 
); 
1467     size_t len 
= wcslen( ws 
) ; 
1468     wxASSERT_MSG(text
.length() == len 
, wxT("GetPartialTextExtents not yet implemented for multichar situations")); 
1470     RectF 
layoutRect(0,0, 100000.0f
, 100000.0f
); 
1471     StringFormat 
strFormat( StringFormat::GenericTypographic() ); 
1473     size_t startPosition 
= 0; 
1474     size_t remainder 
= len
; 
1475     const size_t maxSpan 
= 32; 
1476     CharacterRange
* ranges 
= new CharacterRange
[maxSpan
] ; 
1477     Region
* regions 
= new Region
[maxSpan
]; 
1479     while( remainder 
> 0 ) 
1481         size_t span 
= wxMin( maxSpan
, remainder 
); 
1483         for( size_t i 
= 0 ; i 
< span 
; ++i
) 
1485             ranges
[i
].First 
= 0 ; 
1486             ranges
[i
].Length 
= startPosition
+i
+1 ; 
1488         strFormat
.SetMeasurableCharacterRanges(span
,ranges
); 
1489         strFormat
.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces 
| strFormat
.GetFormatFlags() ); 
1490         m_context
->MeasureCharacterRanges(ws
, -1 , f
,layoutRect
, &strFormat
,span
,regions
) ; 
1493         for ( size_t i 
= 0 ; i 
< span 
; ++i
) 
1495             regions
[i
].GetBounds(&bbox
,m_context
); 
1496             widths
[startPosition
+i
] = bbox
.Width
; 
1499         startPosition 
+= span
; 
1506 bool wxGDIPlusContext::ShouldOffset() const 
1509     if ( !m_pen
.IsNull() ) 
1511         penwidth 
= (int)((wxGDIPlusPenData
*)m_pen
.GetRefData())->GetWidth(); 
1512         if ( penwidth 
== 0 ) 
1515     return ( penwidth 
% 2 ) == 1; 
1518 void* wxGDIPlusContext::GetNativeContext() 
1523 // concatenates this transform with the current transform of this context 
1524 void wxGDIPlusContext::ConcatTransform( const wxGraphicsMatrix
& matrix 
) 
1526     m_context
->MultiplyTransform((Matrix
*) matrix
.GetNativeMatrix()); 
1529 // sets the transform of this context 
1530 void wxGDIPlusContext::SetTransform( const wxGraphicsMatrix
& matrix 
) 
1532     m_context
->SetTransform((Matrix
*) matrix
.GetNativeMatrix()); 
1535 // gets the matrix of this context 
1536 wxGraphicsMatrix 
wxGDIPlusContext::GetTransform() const 
1538     wxGraphicsMatrix matrix 
= CreateMatrix(); 
1539     m_context
->GetTransform((Matrix
*) matrix
.GetNativeMatrix()); 
1543 void wxGDIPlusContext::GetSize( wxDouble
* width
, wxDouble 
*height 
) 
1548 //----------------------------------------------------------------------------- 
1549 // wxGDIPlusRenderer declaration 
1550 //----------------------------------------------------------------------------- 
1552 class wxGDIPlusRenderer 
: public wxGraphicsRenderer
 
1561     virtual ~wxGDIPlusRenderer() 
1563         if ( m_loaded 
== 1 ) 
1571     virtual wxGraphicsContext 
* CreateContext( const wxWindowDC
& dc
); 
1573     virtual wxGraphicsContext 
* CreateContext( const wxMemoryDC
& dc
); 
1575     virtual wxGraphicsContext 
* CreateContext( const wxPrinterDC
& dc
); 
1577     virtual wxGraphicsContext 
* CreateContextFromNativeContext( void * context 
); 
1579     virtual wxGraphicsContext 
* CreateContextFromNativeWindow( void * window 
); 
1581     virtual wxGraphicsContext 
* CreateContext( wxWindow
* window 
); 
1583     virtual wxGraphicsContext 
* CreateMeasuringContext(); 
1587     virtual wxGraphicsPath 
CreatePath(); 
1591     virtual wxGraphicsMatrix 
CreateMatrix( wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0, 
1592         wxDouble tx
=0.0, wxDouble ty
=0.0); 
1595     virtual wxGraphicsPen 
CreatePen(const wxPen
& pen
) ; 
1597     virtual wxGraphicsBrush 
CreateBrush(const wxBrush
& brush 
) ; 
1599     // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 
1600     virtual wxGraphicsBrush 
CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, 
1601         const wxColour
&c1
, const wxColour
&c2
) ; 
1603     // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) 
1604     // with radius r and color cColor 
1605     virtual wxGraphicsBrush 
CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
, 
1606         const wxColour 
&oColor
, const wxColour 
&cColor
) ; 
1609     virtual wxGraphicsFont 
CreateFont( const wxFont 
&font 
, const wxColour 
&col 
= *wxBLACK 
) ; 
1611     // create a native bitmap representation 
1612     virtual wxGraphicsBitmap 
CreateBitmap( const wxBitmap 
&bitmap 
); 
1614     // create a graphics bitmap from a native bitmap 
1615     virtual wxGraphicsBitmap 
CreateBitmapFromNativeBitmap( void* bitmap 
); 
1617     // create a subimage from a native image representation 
1618     virtual wxGraphicsBitmap 
CreateSubBitmap( const wxGraphicsBitmap 
&bitmap
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h  
); 
1621     bool EnsureIsLoaded(); 
1624     friend class wxGDIPlusRendererModule
; 
1628     ULONG_PTR m_gditoken
; 
1630     DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusRenderer
) 
1633 //----------------------------------------------------------------------------- 
1634 // wxGDIPlusRenderer implementation 
1635 //----------------------------------------------------------------------------- 
1637 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusRenderer
,wxGraphicsRenderer
) 
1639 static wxGDIPlusRenderer gs_GDIPlusRenderer
; 
1641 wxGraphicsRenderer
* wxGraphicsRenderer::GetDefaultRenderer() 
1643     return &gs_GDIPlusRenderer
; 
1646 bool wxGDIPlusRenderer::EnsureIsLoaded() 
1648     // load gdiplus.dll if not yet loaded, but don't bother doing it again 
1649     // if we already tried and failed (we don't want to spend lot of time 
1650     // returning NULL from wxGraphicsContext::Create(), which may be called 
1651     // relatively frequently): 
1652     if ( m_loaded 
== -1 ) 
1657     return m_loaded 
== 1; 
1660 // call EnsureIsLoaded() and return returnOnFail value if it fails 
1661 #define ENSURE_LOADED_OR_RETURN(returnOnFail)  \ 
1662     if ( !EnsureIsLoaded() )                   \ 
1663         return (returnOnFail) 
1666 void wxGDIPlusRenderer::Load() 
1668     GdiplusStartupInput input
; 
1669     GdiplusStartupOutput output
; 
1670     if ( GdiplusStartup(&m_gditoken
,&input
,&output
) == Gdiplus::Ok 
) 
1672         wxLogTrace("gdiplus", "successfully initialized GDI+"); 
1677         wxLogTrace("gdiplus", "failed to initialize GDI+, missing gdiplus.dll?"); 
1682 void wxGDIPlusRenderer::Unload() 
1686         GdiplusShutdown(m_gditoken
); 
1689     m_loaded 
= -1; // next Load() will try again 
1692 wxGraphicsContext 
* wxGDIPlusRenderer::CreateContext( const wxWindowDC
& dc
) 
1694     ENSURE_LOADED_OR_RETURN(NULL
); 
1695     wxMSWDCImpl 
*msw 
= wxDynamicCast( dc
.GetImpl() , wxMSWDCImpl 
); 
1696     wxSize sz 
= dc
.GetSize(); 
1697     return new wxGDIPlusContext(this,(HDC
) msw
->GetHDC(), sz
.x
, sz
.y
); 
1700 wxGraphicsContext 
* wxGDIPlusRenderer::CreateContext( const wxPrinterDC
& dc
) 
1702     ENSURE_LOADED_OR_RETURN(NULL
); 
1703     wxMSWDCImpl 
*msw 
= wxDynamicCast( dc
.GetImpl() , wxMSWDCImpl 
); 
1704     wxSize sz 
= dc
.GetSize(); 
1705     return new wxGDIPlusContext(this,(HDC
) msw
->GetHDC(), sz
.x
, sz
.y
); 
1708 wxGraphicsContext 
* wxGDIPlusRenderer::CreateContext( const wxMemoryDC
& dc
) 
1710     ENSURE_LOADED_OR_RETURN(NULL
); 
1711     wxMSWDCImpl 
*msw 
= wxDynamicCast( dc
.GetImpl() , wxMSWDCImpl 
); 
1712     wxSize sz 
= dc
.GetSize(); 
1713     return new wxGDIPlusContext(this,(HDC
) msw
->GetHDC(), sz
.x
, sz
.y
); 
1716 wxGraphicsContext 
* wxGDIPlusRenderer::CreateMeasuringContext() 
1718     ENSURE_LOADED_OR_RETURN(NULL
); 
1719     return new wxGDIPlusMeasuringContext(this); 
1722 wxGraphicsContext 
* wxGDIPlusRenderer::CreateContextFromNativeContext( void * context 
) 
1724     ENSURE_LOADED_OR_RETURN(NULL
); 
1725     return new wxGDIPlusContext(this,(Graphics
*) context
); 
1729 wxGraphicsContext 
* wxGDIPlusRenderer::CreateContextFromNativeWindow( void * window 
) 
1731     ENSURE_LOADED_OR_RETURN(NULL
); 
1732     return new wxGDIPlusContext(this,(HWND
) window
); 
1735 wxGraphicsContext 
* wxGDIPlusRenderer::CreateContext( wxWindow
* window 
) 
1737     ENSURE_LOADED_OR_RETURN(NULL
); 
1738     return new wxGDIPlusContext(this, (HWND
) window
->GetHWND() ); 
1743 wxGraphicsPath 
wxGDIPlusRenderer::CreatePath() 
1745     ENSURE_LOADED_OR_RETURN(wxNullGraphicsPath
); 
1747     m
.SetRefData( new wxGDIPlusPathData(this)); 
1754 wxGraphicsMatrix 
wxGDIPlusRenderer::CreateMatrix( wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
, 
1755                                                            wxDouble tx
, wxDouble ty
) 
1758     ENSURE_LOADED_OR_RETURN(wxNullGraphicsMatrix
); 
1760     wxGDIPlusMatrixData
* data 
= new wxGDIPlusMatrixData( this ); 
1761     data
->Set( a
,b
,c
,d
,tx
,ty 
) ; 
1766 wxGraphicsPen 
wxGDIPlusRenderer::CreatePen(const wxPen
& pen
) 
1768     ENSURE_LOADED_OR_RETURN(wxNullGraphicsPen
); 
1769     if ( !pen
.Ok() || pen
.GetStyle() == wxTRANSPARENT 
) 
1770         return wxNullGraphicsPen
; 
1774         p
.SetRefData(new wxGDIPlusPenData( this, pen 
)); 
1779 wxGraphicsBrush 
wxGDIPlusRenderer::CreateBrush(const wxBrush
& brush 
) 
1781     ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush
); 
1782     if ( !brush
.Ok() || brush
.GetStyle() == wxTRANSPARENT 
) 
1783         return wxNullGraphicsBrush
; 
1787         p
.SetRefData(new wxGDIPlusBrushData( this, brush 
)); 
1792 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 
1793 wxGraphicsBrush 
wxGDIPlusRenderer::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, 
1794                                                                       const wxColour
&c1
, const wxColour
&c2
) 
1796     ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush
); 
1798     wxGDIPlusBrushData
* d 
= new wxGDIPlusBrushData( this ); 
1799     d
->CreateLinearGradientBrush(x1
, y1
, x2
, y2
, c1
, c2
); 
1804 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) 
1805 // with radius r and color cColor 
1806 wxGraphicsBrush 
wxGDIPlusRenderer::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
, 
1807                                                                       const wxColour 
&oColor
, const wxColour 
&cColor
) 
1809     ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush
); 
1811     wxGDIPlusBrushData
* d 
= new wxGDIPlusBrushData( this ); 
1812     d
->CreateRadialGradientBrush(xo
,yo
,xc
,yc
,radius
,oColor
,cColor
); 
1818 wxGraphicsFont 
wxGDIPlusRenderer::CreateFont( const wxFont 
&font 
, const wxColour 
&col 
) 
1820     ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont
); 
1824         p
.SetRefData(new wxGDIPlusFontData( this , font
, col 
)); 
1828         return wxNullGraphicsFont
; 
1831 wxGraphicsBitmap 
wxGDIPlusRenderer::CreateBitmap( const wxBitmap 
&bitmap 
) 
1833     ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap
); 
1837         p
.SetRefData(new wxGDIPlusBitmapData( this , bitmap 
)); 
1841         return wxNullGraphicsBitmap
; 
1844 wxGraphicsBitmap 
wxGDIPlusRenderer::CreateBitmapFromNativeBitmap( void *bitmap 
) 
1846     ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap
); 
1847     if ( bitmap 
!= NULL 
) 
1850         p
.SetRefData(new wxGDIPlusBitmapData( this , (Bitmap
*) bitmap 
)); 
1854         return wxNullGraphicsBitmap
; 
1857 wxGraphicsBitmap 
wxGDIPlusRenderer::CreateSubBitmap( const wxGraphicsBitmap 
&bitmap
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h  
) 
1859     ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap
); 
1860     Bitmap
* image 
= static_cast<wxGDIPlusBitmapData
*>(bitmap
.GetRefData())->GetGDIPlusBitmap(); 
1864         p
.SetRefData(new wxGDIPlusBitmapData( this , image
->Clone( (REAL
) x 
, (REAL
) y 
, (REAL
) w 
, (REAL
) h 
, PixelFormat32bppPARGB
) )); 
1868         return wxNullGraphicsBitmap
; 
1871 // Shutdown GDI+ at app exit, before possible dll unload 
1872 class wxGDIPlusRendererModule 
: public wxModule
 
1875     virtual bool OnInit() { return true; } 
1876     virtual void OnExit() { gs_GDIPlusRenderer
.Unload(); } 
1879     DECLARE_DYNAMIC_CLASS(wxGDIPlusRendererModule
) 
1882 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusRendererModule
, wxModule
) 
1884 // ---------------------------------------------------------------------------- 
1885 // wxMSW-specific parts of wxGCDC 
1886 // ---------------------------------------------------------------------------- 
1888 WXHDC 
wxGCDC::AcquireHDC() 
1890     wxGraphicsContext 
* const gc 
= GetGraphicsContext(); 
1894     Graphics 
* const g 
= static_cast<Graphics 
*>(gc
->GetNativeContext()); 
1895     return g 
? g
->GetHDC() : NULL
; 
1898 void wxGCDC::ReleaseHDC(WXHDC hdc
) 
1903     wxGraphicsContext 
* const gc 
= GetGraphicsContext(); 
1904     wxCHECK_RET( gc
, "can't release HDC because there is no wxGraphicsContext" ); 
1906     Graphics 
* const g 
= static_cast<Graphics 
*>(gc
->GetNativeContext()); 
1907     wxCHECK_RET( g
, "can't release HDC because there is no Graphics" ); 
1909     g
->ReleaseHDC((HDC
)hdc
); 
1912 #endif  // wxUSE_GRAPHICS_CONTEXT