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"
28 #include "wx/dialog.h"
30 #include "wx/bitmap.h"
31 #include "wx/dcmemory.h"
34 #include "wx/dcprint.h"
35 #include "wx/module.h"
38 #include "wx/private/graphics.h"
39 #include "wx/msw/wrapgdip.h"
40 #include "wx/msw/dc.h"
44 WX_DECLARE_STACK(GraphicsState
, GraphicsStates
);
46 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
50 const double RAD2DEG
= 180.0 / M_PI
;
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
57 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
59 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
60 static inline double RadToDeg(double deg
) { return (deg
* 180.0) / M_PI
; }
62 //-----------------------------------------------------------------------------
63 // device context implementation
65 // more and more of the dc functionality should be implemented by calling
66 // the appropricate wxGDIPlusContext, but we will have to do that step by step
67 // also coordinate conversions should be moved to native matrix ops
68 //-----------------------------------------------------------------------------
70 // we always stock two context states, one at entry, to be able to preserve the
71 // state we were called with, the other one after changing to HI Graphics orientation
72 // (this one is used for getting back clippings etc)
74 //-----------------------------------------------------------------------------
75 // wxGraphicsPath implementation
76 //-----------------------------------------------------------------------------
78 #include "wx/msw/private.h" // needs to be before #include <commdlg.h>
80 #if wxUSE_COMMON_DIALOGS && !defined(__WXMICROWIN__)
84 class wxGDIPlusPathData
: public wxGraphicsPathData
87 wxGDIPlusPathData(wxGraphicsRenderer
* renderer
, GraphicsPath
* path
= NULL
);
90 virtual wxGraphicsObjectRefData
*Clone() const;
93 // These are the path primitives from which everything else can be constructed
96 // begins a new subpath at (x,y)
97 virtual void MoveToPoint( wxDouble x
, wxDouble y
);
99 // adds a straight line from the current point to (x,y)
100 virtual void AddLineToPoint( wxDouble x
, wxDouble y
);
102 // adds a cubic Bezier curve from the current point, using two control points and an end point
103 virtual void AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
);
106 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
107 virtual void AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise
) ;
109 // gets the last point of the current path, (0,0) if not yet set
110 virtual void GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const;
113 virtual void AddPath( const wxGraphicsPathData
* path
);
115 // closes the current sub-path
116 virtual void CloseSubpath();
119 // These are convenience functions which - if not available natively will be assembled
120 // using the primitives from above
123 // appends a rectangle as a new closed subpath
124 virtual void AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
) ;
127 // appends an ellipsis as a new closed subpath fitting the passed rectangle
128 virtual void AddEllipsis( wxDouble x, wxDouble y, wxDouble w , wxDouble h ) ;
130 // 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)
131 virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r ) ;
134 // returns the native path
135 virtual void * GetNativePath() const { return m_path
; }
137 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
138 virtual void UnGetNativePath(void * WXUNUSED(path
)) const {}
140 // transforms each point of this path by the matrix
141 virtual void Transform( const wxGraphicsMatrixData
* matrix
) ;
143 // gets the bounding box enclosing all points (possibly including control points)
144 virtual void GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*h
) const;
146 virtual bool Contains( wxDouble x
, wxDouble y
, int fillStyle
= wxODDEVEN_RULE
) const;
149 GraphicsPath
* m_path
;
152 class wxGDIPlusMatrixData
: public wxGraphicsMatrixData
155 wxGDIPlusMatrixData(wxGraphicsRenderer
* renderer
, Matrix
* matrix
= NULL
) ;
156 virtual ~wxGDIPlusMatrixData() ;
158 virtual wxGraphicsObjectRefData
* Clone() const ;
160 // concatenates the matrix
161 virtual void Concat( const wxGraphicsMatrixData
*t
);
163 // sets the matrix to the respective values
164 virtual void Set(wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
165 wxDouble tx
=0.0, wxDouble ty
=0.0);
167 // gets the component valuess of the matrix
168 virtual void Get(wxDouble
* a
=NULL
, wxDouble
* b
=NULL
, wxDouble
* c
=NULL
,
169 wxDouble
* d
=NULL
, wxDouble
* tx
=NULL
, wxDouble
* ty
=NULL
) const;
171 // makes this the inverse matrix
172 virtual void Invert();
174 // returns true if the elements of the transformation matrix are equal ?
175 virtual bool IsEqual( const wxGraphicsMatrixData
* t
) const ;
177 // return true if this is the identity matrix
178 virtual bool IsIdentity() const;
184 // add the translation to this matrix
185 virtual void Translate( wxDouble dx
, wxDouble dy
);
187 // add the scale to this matrix
188 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
190 // add the rotation to this matrix (radians)
191 virtual void Rotate( wxDouble angle
);
194 // apply the transforms
197 // applies that matrix to the point
198 virtual void TransformPoint( wxDouble
*x
, wxDouble
*y
) const;
200 // applies the matrix except for translations
201 virtual void TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const;
203 // returns the native representation
204 virtual void * GetNativeMatrix() const;
209 class wxGDIPlusPenData
: public wxGraphicsObjectRefData
212 wxGDIPlusPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
);
217 virtual wxDouble
GetWidth() { return m_width
; }
218 virtual Pen
* GetGDIPlusPen() { return m_pen
; }
228 class wxGDIPlusBrushData
: public wxGraphicsObjectRefData
231 wxGDIPlusBrushData( wxGraphicsRenderer
* renderer
);
232 wxGDIPlusBrushData( wxGraphicsRenderer
* renderer
, const wxBrush
&brush
);
233 ~wxGDIPlusBrushData ();
235 void CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
236 const wxColour
&c1
, const wxColour
&c2
);
237 void CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
238 const wxColour
&oColor
, const wxColour
&cColor
);
239 virtual Brush
* GetGDIPlusBrush() { return m_brush
; }
247 GraphicsPath
* m_brushPath
;
250 class WXDLLIMPEXP_CORE wxGDIPlusBitmapData
: public wxGraphicsObjectRefData
253 wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
, Bitmap
* bitmap
);
254 wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
, const wxBitmap
&bmp
);
255 ~wxGDIPlusBitmapData ();
257 virtual Bitmap
* GetGDIPlusBitmap() { return m_bitmap
; }
264 class wxGDIPlusFontData
: public wxGraphicsObjectRefData
267 wxGDIPlusFontData( wxGraphicsRenderer
* renderer
, const wxFont
&font
, const wxColour
& col
);
268 ~wxGDIPlusFontData();
270 virtual Brush
* GetGDIPlusBrush() { return m_textBrush
; }
271 virtual Font
* GetGDIPlusFont() { return m_font
; }
277 class wxGDIPlusContext
: public wxGraphicsContext
280 wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HDC hdc
);
281 wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HWND hwnd
);
282 wxGDIPlusContext( wxGraphicsRenderer
* renderer
, Graphics
* gr
);
285 virtual ~wxGDIPlusContext();
287 virtual void Clip( const wxRegion
®ion
);
288 // clips drawings to the rect
289 virtual void Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
291 // resets the clipping to original extent
292 virtual void ResetClip();
294 virtual void * GetNativeContext();
296 virtual void StrokePath( const wxGraphicsPath
& p
);
297 virtual void FillPath( const wxGraphicsPath
& p
, int fillStyle
= wxODDEVEN_RULE
);
299 // stroke lines connecting each of the points
300 virtual void StrokeLines( size_t n
, const wxPoint2DDouble
*points
);
303 virtual void DrawLines( size_t n
, const wxPoint2DDouble
*points
, int fillStyle
= wxODDEVEN_RULE
);
305 virtual void Translate( wxDouble dx
, wxDouble dy
);
306 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
307 virtual void Rotate( wxDouble angle
);
309 // concatenates this transform with the current transform of this context
310 virtual void ConcatTransform( const wxGraphicsMatrix
& matrix
);
312 // sets the transform of this context
313 virtual void SetTransform( const wxGraphicsMatrix
& matrix
);
315 // gets the matrix of this context
316 virtual wxGraphicsMatrix
GetTransform() const;
318 virtual void DrawBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
319 virtual void DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
320 virtual void DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
321 virtual void PushState();
322 virtual void PopState();
324 virtual void DrawText( const wxString
&str
, wxDouble x
, wxDouble y
);
325 virtual void GetTextExtent( const wxString
&str
, wxDouble
*width
, wxDouble
*height
,
326 wxDouble
*descent
, wxDouble
*externalLeading
) const;
327 virtual void GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const;
328 virtual bool ShouldOffset() const;
335 GraphicsStates m_stateStack
;
336 GraphicsState m_state1
;
337 GraphicsState m_state2
;
339 DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusContext
)
342 class WXDLLIMPEXP_CORE wxGDIPlusMeasuringContext
: public wxGDIPlusContext
345 wxGDIPlusMeasuringContext( wxGraphicsRenderer
* renderer
) : wxGDIPlusContext( renderer
, m_hdc
= GetDC(NULL
) )
348 wxGDIPlusMeasuringContext()
352 virtual ~wxGDIPlusMeasuringContext()
354 ReleaseDC( NULL
, m_hdc
);
359 DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusMeasuringContext
)
362 //-----------------------------------------------------------------------------
363 // wxGDIPlusPen implementation
364 //-----------------------------------------------------------------------------
366 wxGDIPlusPenData::~wxGDIPlusPenData()
373 void wxGDIPlusPenData::Init()
380 wxGDIPlusPenData::wxGDIPlusPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
)
381 : wxGraphicsObjectRefData(renderer
)
384 m_width
= pen
.GetWidth();
388 m_pen
= new Pen(Color( pen
.GetColour().Alpha() , pen
.GetColour().Red() ,
389 pen
.GetColour().Green() , pen
.GetColour().Blue() ), m_width
);
392 switch ( pen
.GetCap() )
398 case wxCAP_PROJECTING
:
403 cap
= LineCapFlat
; // TODO verify
410 m_pen
->SetLineCap(cap
,cap
, DashCapFlat
);
413 switch ( pen
.GetJoin() )
416 join
= LineJoinBevel
;
420 join
= LineJoinMiter
;
424 join
= LineJoinRound
;
428 join
= LineJoinMiter
;
432 m_pen
->SetLineJoin(join
);
434 m_pen
->SetDashStyle(DashStyleSolid
);
436 DashStyle dashStyle
= DashStyleSolid
;
437 switch ( pen
.GetStyle() )
443 dashStyle
= DashStyleDot
;
447 dashStyle
= DashStyleDash
; // TODO verify
451 dashStyle
= DashStyleDash
;
455 dashStyle
= DashStyleDashDot
;
459 dashStyle
= DashStyleCustom
;
461 int count
= pen
.GetDashes( &dashes
);
462 if ((dashes
!= NULL
) && (count
> 0))
464 REAL
*userLengths
= new REAL
[count
];
465 for ( int i
= 0; i
< count
; ++i
)
467 userLengths
[i
] = dashes
[i
];
469 m_pen
->SetDashPattern( userLengths
, count
);
470 delete[] userLengths
;
476 wxBitmap
* bmp
= pen
.GetStipple();
477 if ( bmp
&& bmp
->Ok() )
479 m_penImage
= Bitmap::FromHBITMAP((HBITMAP
)bmp
->GetHBITMAP(),(HPALETTE
)bmp
->GetPalette()->GetHPALETTE());
480 m_penBrush
= new TextureBrush(m_penImage
);
481 m_pen
->SetBrush( m_penBrush
);
487 if ( pen
.GetStyle() >= wxFIRST_HATCH
&& pen
.GetStyle() <= wxLAST_HATCH
)
489 HatchStyle style
= HatchStyleHorizontal
;
490 switch( pen
.GetStyle() )
492 case wxBDIAGONAL_HATCH
:
493 style
= HatchStyleBackwardDiagonal
;
495 case wxCROSSDIAG_HATCH
:
496 style
= HatchStyleDiagonalCross
;
498 case wxFDIAGONAL_HATCH
:
499 style
= HatchStyleForwardDiagonal
;
502 style
= HatchStyleCross
;
504 case wxHORIZONTAL_HATCH
:
505 style
= HatchStyleHorizontal
;
507 case wxVERTICAL_HATCH
:
508 style
= HatchStyleVertical
;
512 m_penBrush
= new HatchBrush(style
,Color( pen
.GetColour().Alpha() , pen
.GetColour().Red() ,
513 pen
.GetColour().Green() , pen
.GetColour().Blue() ), Color::Transparent
);
514 m_pen
->SetBrush( m_penBrush
);
518 if ( dashStyle
!= DashStyleSolid
)
519 m_pen
->SetDashStyle(dashStyle
);
522 //-----------------------------------------------------------------------------
523 // wxGDIPlusBrush implementation
524 //-----------------------------------------------------------------------------
526 wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer
* renderer
)
527 : wxGraphicsObjectRefData(renderer
)
532 wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer
* renderer
, const wxBrush
&brush
)
533 : wxGraphicsObjectRefData(renderer
)
536 if ( brush
.GetStyle() == wxSOLID
)
538 m_brush
= new SolidBrush( Color( brush
.GetColour().Alpha() , brush
.GetColour().Red() ,
539 brush
.GetColour().Green() , brush
.GetColour().Blue() ) );
541 else if ( brush
.IsHatch() )
543 HatchStyle style
= HatchStyleHorizontal
;
544 switch( brush
.GetStyle() )
546 case wxBDIAGONAL_HATCH
:
547 style
= HatchStyleBackwardDiagonal
;
549 case wxCROSSDIAG_HATCH
:
550 style
= HatchStyleDiagonalCross
;
552 case wxFDIAGONAL_HATCH
:
553 style
= HatchStyleForwardDiagonal
;
556 style
= HatchStyleCross
;
558 case wxHORIZONTAL_HATCH
:
559 style
= HatchStyleHorizontal
;
561 case wxVERTICAL_HATCH
:
562 style
= HatchStyleVertical
;
566 m_brush
= new HatchBrush(style
,Color( brush
.GetColour().Alpha() , brush
.GetColour().Red() ,
567 brush
.GetColour().Green() , brush
.GetColour().Blue() ), Color::Transparent
);
571 wxBitmap
* bmp
= brush
.GetStipple();
572 if ( bmp
&& bmp
->Ok() )
574 wxDELETE( m_brushImage
);
575 m_brushImage
= Bitmap::FromHBITMAP((HBITMAP
)bmp
->GetHBITMAP(),(HPALETTE
)bmp
->GetPalette()->GetHPALETTE());
576 m_brush
= new TextureBrush(m_brushImage
);
581 wxGDIPlusBrushData::~wxGDIPlusBrushData()
588 void wxGDIPlusBrushData::Init()
595 void wxGDIPlusBrushData::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, const wxColour
&c1
, const wxColour
&c2
)
597 m_brush
= new LinearGradientBrush( PointF( x1
,y1
) , PointF( x2
,y2
),
598 Color( c1
.Alpha(), c1
.Red(),c1
.Green() , c1
.Blue() ),
599 Color( c2
.Alpha(), c2
.Red(),c2
.Green() , c2
.Blue() ));
602 void wxGDIPlusBrushData::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
603 const wxColour
&oColor
, const wxColour
&cColor
)
605 // Create a path that consists of a single circle.
606 m_brushPath
= new GraphicsPath();
607 m_brushPath
->AddEllipse( (REAL
)(xc
-radius
), (REAL
)(yc
-radius
), (REAL
)(2*radius
), (REAL
)(2*radius
));
609 PathGradientBrush
*b
= new PathGradientBrush(m_brushPath
);
611 b
->SetCenterPoint( PointF(xo
,yo
));
612 b
->SetCenterColor(Color( oColor
.Alpha(), oColor
.Red(),oColor
.Green() , oColor
.Blue() ));
614 Color colors
[] = {Color( cColor
.Alpha(), cColor
.Red(),cColor
.Green() , cColor
.Blue() )};
616 b
->SetSurroundColors(colors
, &count
);
619 //-----------------------------------------------------------------------------
620 // wxGDIPlusFont implementation
621 //-----------------------------------------------------------------------------
623 wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer
* renderer
, const wxFont
&font
,
624 const wxColour
& col
) : wxGraphicsObjectRefData( renderer
)
629 wxWCharBuffer s
= font
.GetFaceName().wc_str( *wxConvUI
);
630 int size
= font
.GetPointSize();
631 int style
= FontStyleRegular
;
632 if ( font
.GetStyle() == wxFONTSTYLE_ITALIC
)
633 style
|= FontStyleItalic
;
634 if ( font
.GetUnderlined() )
635 style
|= FontStyleUnderline
;
636 if ( font
.GetWeight() == wxFONTWEIGHT_BOLD
)
637 style
|= FontStyleBold
;
638 m_font
= new Font( s
, size
, style
);
639 m_textBrush
= new SolidBrush( Color( col
.Alpha() , col
.Red() ,
640 col
.Green() , col
.Blue() ));
643 wxGDIPlusFontData::~wxGDIPlusFontData()
649 // the built-in conversions functions create non-premultiplied bitmaps, while GDIPlus needs them in the
650 // premultiplied format, therefore in the failing cases we create a new bitmap using the non-premultiplied
651 // bytes as parameter, since there is no real copying of the data going in, only references are stored
652 // m_helper has to be kept alive as well
654 //-----------------------------------------------------------------------------
655 // wxGDIPlusBitmapData implementation
656 //-----------------------------------------------------------------------------
658 wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
, Bitmap
* bitmap
) :
659 wxGraphicsObjectRefData( renderer
), m_bitmap( bitmap
)
664 wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer
* renderer
,
665 const wxBitmap
&bmp
) : wxGraphicsObjectRefData( renderer
)
670 Bitmap
* image
= NULL
;
673 Bitmap
interim((HBITMAP
)bmp
.GetHBITMAP(),(HPALETTE
)bmp
.GetPalette()->GetHPALETTE()) ;
675 size_t width
= interim
.GetWidth();
676 size_t height
= interim
.GetHeight();
677 Rect
bounds(0,0,width
,height
);
679 image
= new Bitmap(width
,height
,PixelFormat32bppPARGB
) ;
681 Bitmap
interimMask((HBITMAP
)bmp
.GetMask()->GetMaskBitmap(),NULL
);
682 wxASSERT(interimMask
.GetPixelFormat() == PixelFormat1bppIndexed
);
684 BitmapData dataMask
;
685 interimMask
.LockBits(&bounds
,ImageLockModeRead
,
686 interimMask
.GetPixelFormat(),&dataMask
);
689 BitmapData imageData
;
690 image
->LockBits(&bounds
,ImageLockModeWrite
, PixelFormat32bppPARGB
, &imageData
);
692 BYTE maskPattern
= 0 ;
696 for ( size_t y
= 0 ; y
< height
; ++y
)
699 for( size_t x
= 0 ; x
< width
; ++x
)
704 maskByte
= *((BYTE
*)dataMask
.Scan0
+ dataMask
.Stride
*y
+ maskIndex
);
708 maskPattern
= maskPattern
>> 1;
710 ARGB
*dest
= (ARGB
*)((BYTE
*)imageData
.Scan0
+ imageData
.Stride
*y
+ x
*4);
711 if ( (maskByte
& maskPattern
) == 0 )
716 interim
.GetPixel(x
,y
,&c
) ;
717 *dest
= (c
.GetValue() | Color::AlphaMask
);
722 image
->UnlockBits(&imageData
);
724 interimMask
.UnlockBits(&dataMask
);
725 interim
.UnlockBits(&dataMask
);
729 image
= Bitmap::FromHBITMAP((HBITMAP
)bmp
.GetHBITMAP(),(HPALETTE
)bmp
.GetPalette()->GetHPALETTE());
730 if ( bmp
.HasAlpha() && GetPixelFormatSize(image
->GetPixelFormat()) == 32 )
732 size_t width
= image
->GetWidth();
733 size_t height
= image
->GetHeight();
734 Rect
bounds(0,0,width
,height
);
735 static BitmapData data
;
739 m_helper
->LockBits(&bounds
, ImageLockModeRead
,
740 m_helper
->GetPixelFormat(),&data
);
742 image
= new Bitmap(data
.Width
, data
.Height
, data
.Stride
,
743 PixelFormat32bppPARGB
, (BYTE
*) data
.Scan0
);
745 m_helper
->UnlockBits(&data
);
752 wxGDIPlusBitmapData::~wxGDIPlusBitmapData()
758 //-----------------------------------------------------------------------------
759 // wxGDIPlusPath implementation
760 //-----------------------------------------------------------------------------
762 wxGDIPlusPathData::wxGDIPlusPathData(wxGraphicsRenderer
* renderer
, GraphicsPath
* path
) : wxGraphicsPathData(renderer
)
767 m_path
= new GraphicsPath();
770 wxGDIPlusPathData::~wxGDIPlusPathData()
775 wxGraphicsObjectRefData
* wxGDIPlusPathData::Clone() const
777 return new wxGDIPlusPathData( GetRenderer() , m_path
->Clone());
784 void wxGDIPlusPathData::MoveToPoint( wxDouble x
, wxDouble y
)
786 m_path
->StartFigure();
787 m_path
->AddLine((REAL
) x
,(REAL
) y
,(REAL
) x
,(REAL
) y
);
790 void wxGDIPlusPathData::AddLineToPoint( wxDouble x
, wxDouble y
)
792 m_path
->AddLine((REAL
) x
,(REAL
) y
,(REAL
) x
,(REAL
) y
);
795 void wxGDIPlusPathData::CloseSubpath()
797 m_path
->CloseFigure();
800 void wxGDIPlusPathData::AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
)
806 m_path
->GetLastPoint(&start
);
807 m_path
->AddBezier(start
,c1
,c2
,end
);
810 // gets the last point of the current path, (0,0) if not yet set
811 void wxGDIPlusPathData::GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const
814 m_path
->GetLastPoint(&start
);
819 void wxGDIPlusPathData::AddArc( wxDouble x
, wxDouble y
, wxDouble r
, double startAngle
, double endAngle
, bool clockwise
)
821 double sweepAngle
= endAngle
- startAngle
;
822 if( fabs(sweepAngle
) >= 2*M_PI
)
824 sweepAngle
= 2 * M_PI
;
831 sweepAngle
+= 2 * M_PI
;
836 sweepAngle
-= 2 * M_PI
;
840 m_path
->AddArc((REAL
) (x
-r
),(REAL
) (y
-r
),(REAL
) (2*r
),(REAL
) (2*r
),RadToDeg(startAngle
),RadToDeg(sweepAngle
));
843 void wxGDIPlusPathData::AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
845 m_path
->AddRectangle(RectF(x
,y
,w
,h
));
848 void wxGDIPlusPathData::AddPath( const wxGraphicsPathData
* path
)
850 m_path
->AddPath( (GraphicsPath
*) path
->GetNativePath(), FALSE
);
854 // transforms each point of this path by the matrix
855 void wxGDIPlusPathData::Transform( const wxGraphicsMatrixData
* matrix
)
857 m_path
->Transform( (Matrix
*) matrix
->GetNativeMatrix() );
860 // gets the bounding box enclosing all points (possibly including control points)
861 void wxGDIPlusPathData::GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*h
) const
864 m_path
->GetBounds( &bounds
, NULL
, NULL
) ;
871 bool wxGDIPlusPathData::Contains( wxDouble x
, wxDouble y
, int fillStyle
) const
873 m_path
->SetFillMode( fillStyle
== wxODDEVEN_RULE
? FillModeAlternate
: FillModeWinding
);
874 return m_path
->IsVisible( (FLOAT
) x
,(FLOAT
) y
) == TRUE
;
877 //-----------------------------------------------------------------------------
878 // wxGDIPlusMatrixData implementation
879 //-----------------------------------------------------------------------------
881 wxGDIPlusMatrixData::wxGDIPlusMatrixData(wxGraphicsRenderer
* renderer
, Matrix
* matrix
)
882 : wxGraphicsMatrixData(renderer
)
887 m_matrix
= new Matrix();
890 wxGDIPlusMatrixData::~wxGDIPlusMatrixData()
895 wxGraphicsObjectRefData
*wxGDIPlusMatrixData::Clone() const
897 return new wxGDIPlusMatrixData( GetRenderer(), m_matrix
->Clone());
900 // concatenates the matrix
901 void wxGDIPlusMatrixData::Concat( const wxGraphicsMatrixData
*t
)
903 m_matrix
->Multiply( (Matrix
*) t
->GetNativeMatrix());
906 // sets the matrix to the respective values
907 void wxGDIPlusMatrixData::Set(wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
908 wxDouble tx
, wxDouble ty
)
910 m_matrix
->SetElements(a
,b
,c
,d
,tx
,ty
);
913 // gets the component valuess of the matrix
914 void wxGDIPlusMatrixData::Get(wxDouble
* a
, wxDouble
* b
, wxDouble
* c
,
915 wxDouble
* d
, wxDouble
* tx
, wxDouble
* ty
) const
918 m_matrix
->GetElements(elements
);
919 if (a
) *a
= elements
[0];
920 if (b
) *b
= elements
[1];
921 if (c
) *c
= elements
[2];
922 if (d
) *d
= elements
[3];
923 if (tx
) *tx
= elements
[4];
924 if (ty
) *ty
= elements
[5];
927 // makes this the inverse matrix
928 void wxGDIPlusMatrixData::Invert()
933 // returns true if the elements of the transformation matrix are equal ?
934 bool wxGDIPlusMatrixData::IsEqual( const wxGraphicsMatrixData
* t
) const
936 return m_matrix
->Equals((Matrix
*) t
->GetNativeMatrix())== TRUE
;
939 // return true if this is the identity matrix
940 bool wxGDIPlusMatrixData::IsIdentity() const
942 return m_matrix
->IsIdentity() == TRUE
;
949 // add the translation to this matrix
950 void wxGDIPlusMatrixData::Translate( wxDouble dx
, wxDouble dy
)
952 m_matrix
->Translate(dx
,dy
);
955 // add the scale to this matrix
956 void wxGDIPlusMatrixData::Scale( wxDouble xScale
, wxDouble yScale
)
958 m_matrix
->Scale(xScale
,yScale
);
961 // add the rotation to this matrix (radians)
962 void wxGDIPlusMatrixData::Rotate( wxDouble angle
)
964 m_matrix
->Rotate( angle
);
968 // apply the transforms
971 // applies that matrix to the point
972 void wxGDIPlusMatrixData::TransformPoint( wxDouble
*x
, wxDouble
*y
) const
975 m_matrix
->TransformPoints(&pt
);
980 // applies the matrix except for translations
981 void wxGDIPlusMatrixData::TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const
984 m_matrix
->TransformVectors(&pt
);
989 // returns the native representation
990 void * wxGDIPlusMatrixData::GetNativeMatrix() const
995 //-----------------------------------------------------------------------------
996 // wxGDIPlusContext implementation
997 //-----------------------------------------------------------------------------
999 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusContext
,wxGraphicsContext
)
1000 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusMeasuringContext
,wxGDIPlusContext
)
1002 class wxGDIPlusOffsetHelper
1005 wxGDIPlusOffsetHelper( Graphics
* gr
, bool offset
)
1010 m_gr
->TranslateTransform( 0.5, 0.5 );
1012 ~wxGDIPlusOffsetHelper( )
1015 m_gr
->TranslateTransform( -0.5, -0.5 );
1022 wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HDC hdc
)
1023 : wxGraphicsContext(renderer
)
1026 m_context
= new Graphics( hdc
);
1030 wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer
* renderer
, HWND hwnd
)
1031 : wxGraphicsContext(renderer
)
1034 m_context
= new Graphics( hwnd
);
1038 wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer
* renderer
, Graphics
* gr
)
1039 : wxGraphicsContext(renderer
)
1046 wxGDIPlusContext::wxGDIPlusContext() : wxGraphicsContext(NULL
)
1051 void wxGDIPlusContext::Init()
1058 void wxGDIPlusContext::SetDefaults()
1060 m_context
->SetTextRenderingHint(TextRenderingHintSystemDefault
);
1061 m_context
->SetPixelOffsetMode(PixelOffsetModeHalf
);
1062 m_context
->SetSmoothingMode(SmoothingModeHighQuality
);
1063 m_state1
= m_context
->Save();
1064 m_state2
= m_context
->Save();
1067 wxGDIPlusContext::~wxGDIPlusContext()
1071 m_context
->Restore( m_state2
);
1072 m_context
->Restore( m_state1
);
1078 void wxGDIPlusContext::Clip( const wxRegion
®ion
)
1080 Region
rgn((HRGN
)region
.GetHRGN());
1081 m_context
->SetClip(&rgn
,CombineModeIntersect
);
1084 void wxGDIPlusContext::Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1086 m_context
->SetClip(RectF(x
,y
,w
,h
),CombineModeIntersect
);
1089 void wxGDIPlusContext::ResetClip()
1091 m_context
->ResetClip();
1094 void wxGDIPlusContext::StrokeLines( size_t n
, const wxPoint2DDouble
*points
)
1096 if ( !m_pen
.IsNull() )
1098 wxGDIPlusOffsetHelper
helper( m_context
, ShouldOffset() );
1099 Point
*cpoints
= new Point
[n
];
1100 for (size_t i
= 0; i
< n
; i
++)
1102 cpoints
[i
].X
= (int)(points
[i
].m_x
);
1103 cpoints
[i
].Y
= (int)(points
[i
].m_y
);
1105 } // for (size_t i = 0; i < n; i++)
1106 m_context
->DrawLines( ((wxGDIPlusPenData
*)m_pen
.GetGraphicsData())->GetGDIPlusPen() , cpoints
, n
) ;
1111 void wxGDIPlusContext::DrawLines( size_t n
, const wxPoint2DDouble
*points
, int WXUNUSED(fillStyle
) )
1113 wxGDIPlusOffsetHelper
helper( m_context
, ShouldOffset() );
1114 Point
*cpoints
= new Point
[n
];
1115 for (size_t i
= 0; i
< n
; i
++)
1117 cpoints
[i
].X
= (int)(points
[i
].m_x
);
1118 cpoints
[i
].Y
= (int)(points
[i
].m_y
);
1120 } // for (int i = 0; i < n; i++)
1121 if ( !m_brush
.IsNull() )
1122 m_context
->FillPolygon( ((wxGDIPlusBrushData
*)m_brush
.GetRefData())->GetGDIPlusBrush() , cpoints
, n
) ;
1123 if ( !m_pen
.IsNull() )
1124 m_context
->DrawLines( ((wxGDIPlusPenData
*)m_pen
.GetGraphicsData())->GetGDIPlusPen() , cpoints
, n
) ;
1128 void wxGDIPlusContext::StrokePath( const wxGraphicsPath
& path
)
1130 if ( !m_pen
.IsNull() )
1132 wxGDIPlusOffsetHelper
helper( m_context
, ShouldOffset() );
1133 m_context
->DrawPath( ((wxGDIPlusPenData
*)m_pen
.GetGraphicsData())->GetGDIPlusPen() , (GraphicsPath
*) path
.GetNativePath() );
1137 void wxGDIPlusContext::FillPath( const wxGraphicsPath
& path
, int fillStyle
)
1139 if ( !m_brush
.IsNull() )
1141 wxGDIPlusOffsetHelper
helper( m_context
, ShouldOffset() );
1142 ((GraphicsPath
*) path
.GetNativePath())->SetFillMode( fillStyle
== wxODDEVEN_RULE
? FillModeAlternate
: FillModeWinding
);
1143 m_context
->FillPath( ((wxGDIPlusBrushData
*)m_brush
.GetRefData())->GetGDIPlusBrush() ,
1144 (GraphicsPath
*) path
.GetNativePath());
1148 void wxGDIPlusContext::Rotate( wxDouble angle
)
1150 m_context
->RotateTransform( RadToDeg(angle
) );
1153 void wxGDIPlusContext::Translate( wxDouble dx
, wxDouble dy
)
1155 m_context
->TranslateTransform( dx
, dy
);
1158 void wxGDIPlusContext::Scale( wxDouble xScale
, wxDouble yScale
)
1160 m_context
->ScaleTransform(xScale
,yScale
);
1163 void wxGDIPlusContext::PushState()
1165 GraphicsState state
= m_context
->Save();
1166 m_stateStack
.push(state
);
1169 void wxGDIPlusContext::PopState()
1171 GraphicsState state
= m_stateStack
.top();
1173 m_context
->Restore(state
);
1176 void wxGDIPlusContext::DrawBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1178 Bitmap
* image
= static_cast<wxGDIPlusBitmapData
*>(bmp
.GetRefData())->GetGDIPlusBitmap();
1181 if( image
->GetWidth() != (UINT
) w
|| image
->GetHeight() != (UINT
) h
)
1183 Rect
drawRect((REAL
) x
, (REAL
)y
, (REAL
)w
, (REAL
)h
);
1184 m_context
->SetPixelOffsetMode( PixelOffsetModeNone
);
1185 m_context
->DrawImage(image
, drawRect
, 0 , 0 , image
->GetWidth()-1, image
->GetHeight()-1, UnitPixel
) ;
1186 m_context
->SetPixelOffsetMode( PixelOffsetModeHalf
);
1189 m_context
->DrawImage(image
,(REAL
) x
,(REAL
) y
,(REAL
) w
,(REAL
) h
) ;
1193 void wxGDIPlusContext::DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1195 wxGraphicsBitmap bitmap
= GetRenderer()->CreateBitmap(bmp
);
1196 DrawBitmap(bitmap
, x
, y
, w
, h
);
1199 void wxGDIPlusContext::DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1201 // the built-in conversion fails when there is alpha in the HICON (eg XP style icons), we can only
1202 // find out by looking at the bitmap data whether there really was alpha in it
1203 HICON hIcon
= (HICON
)icon
.GetHICON();
1205 // IconInfo creates the bitmaps for color and mask, we must dispose of them after use
1206 if (!GetIconInfo(hIcon
,&iconInfo
))
1209 Bitmap
interim(iconInfo
.hbmColor
,NULL
);
1211 Bitmap
* image
= NULL
;
1213 // if it's not 32 bit, it doesn't have an alpha channel, note that since the conversion doesn't
1214 // work correctly, asking IsAlphaPixelFormat at this point fails as well
1215 if( GetPixelFormatSize(interim
.GetPixelFormat())!= 32 )
1217 image
= Bitmap::FromHICON(hIcon
);
1221 size_t width
= interim
.GetWidth();
1222 size_t height
= interim
.GetHeight();
1223 Rect
bounds(0,0,width
,height
);
1226 interim
.LockBits(&bounds
, ImageLockModeRead
,
1227 interim
.GetPixelFormat(),&data
);
1229 bool hasAlpha
= false;
1230 for ( size_t y
= 0 ; y
< height
&& !hasAlpha
; ++y
)
1232 for( size_t x
= 0 ; x
< width
&& !hasAlpha
; ++x
)
1234 ARGB
*dest
= (ARGB
*)((BYTE
*)data
.Scan0
+ data
.Stride
*y
+ x
*4);
1235 if ( ( *dest
& Color::AlphaMask
) != 0 )
1242 image
= new Bitmap(data
.Width
, data
.Height
, data
.Stride
,
1243 PixelFormat32bppARGB
, (BYTE
*) data
.Scan0
);
1247 image
= Bitmap::FromHICON(hIcon
);
1250 interim
.UnlockBits(&data
);
1253 m_context
->DrawImage(image
,(REAL
) x
,(REAL
) y
,(REAL
) w
,(REAL
) h
) ;
1256 DeleteObject(iconInfo
.hbmColor
);
1257 DeleteObject(iconInfo
.hbmMask
);
1260 void wxGDIPlusContext::DrawText( const wxString
&str
, wxDouble x
, wxDouble y
)
1262 if ( m_font
.IsNull() || str
.IsEmpty())
1265 wxWCharBuffer s
= str
.wc_str( *wxConvUI
);
1266 m_context
->DrawString( s
, -1 , ((wxGDIPlusFontData
*)m_font
.GetRefData())->GetGDIPlusFont() ,
1267 PointF( x
, y
) , StringFormat::GenericTypographic() , ((wxGDIPlusFontData
*)m_font
.GetRefData())->GetGDIPlusBrush() );
1270 void wxGDIPlusContext::GetTextExtent( const wxString
&str
, wxDouble
*width
, wxDouble
*height
,
1271 wxDouble
*descent
, wxDouble
*externalLeading
) const
1273 wxWCharBuffer s
= str
.wc_str( *wxConvUI
);
1274 FontFamily ffamily
;
1275 Font
* f
= ((wxGDIPlusFontData
*)m_font
.GetRefData())->GetGDIPlusFont();
1277 f
->GetFamily(&ffamily
) ;
1279 REAL factorY
= m_context
->GetDpiY() / 72.0 ;
1281 REAL rDescent
= ffamily
.GetCellDescent(FontStyleRegular
) *
1282 f
->GetSize() / ffamily
.GetEmHeight(FontStyleRegular
);
1283 REAL rAscent
= ffamily
.GetCellAscent(FontStyleRegular
) *
1284 f
->GetSize() / ffamily
.GetEmHeight(FontStyleRegular
);
1285 REAL rHeight
= ffamily
.GetLineSpacing(FontStyleRegular
) *
1286 f
->GetSize() / ffamily
.GetEmHeight(FontStyleRegular
);
1289 *height
= rHeight
* factorY
;
1291 *descent
= rDescent
* factorY
;
1292 if ( externalLeading
)
1293 *externalLeading
= (rHeight
- rAscent
- rDescent
) * factorY
;
1294 // measuring empty strings is not guaranteed, so do it by hand
1302 RectF
layoutRect(0,0, 100000.0f
, 100000.0f
);
1303 StringFormat
strFormat( StringFormat::GenericTypographic() );
1304 strFormat
.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces
| strFormat
.GetFormatFlags() );
1307 m_context
->MeasureString((const wchar_t *) s
, wcslen(s
) , f
, layoutRect
, &strFormat
, &bounds
) ;
1309 *width
= bounds
.Width
;
1313 void wxGDIPlusContext::GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const
1316 widths
.Add(0, text
.length());
1321 Font
* f
= ((wxGDIPlusFontData
*)m_font
.GetRefData())->GetGDIPlusFont();
1322 wxWCharBuffer ws
= text
.wc_str( *wxConvUI
);
1323 size_t len
= wcslen( ws
) ;
1324 wxASSERT_MSG(text
.length() == len
, wxT("GetPartialTextExtents not yet implemented for multichar situations"));
1326 RectF
layoutRect(0,0, 100000.0f
, 100000.0f
);
1327 StringFormat
strFormat( StringFormat::GenericTypographic() );
1329 CharacterRange
* ranges
= new CharacterRange
[len
] ;
1330 Region
* regions
= new Region
[len
];
1331 for( size_t i
= 0 ; i
< len
; ++i
)
1333 ranges
[i
].First
= i
;
1334 ranges
[i
].Length
= 1 ;
1336 strFormat
.SetMeasurableCharacterRanges(len
,ranges
);
1337 strFormat
.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces
| strFormat
.GetFormatFlags() );
1338 m_context
->MeasureCharacterRanges(ws
, -1 , f
,layoutRect
, &strFormat
,1,regions
) ;
1341 for ( size_t i
= 0 ; i
< len
; ++i
)
1343 regions
[i
].GetBounds(&bbox
,m_context
);
1344 widths
[i
] = bbox
.GetRight()-bbox
.GetLeft();
1348 bool wxGDIPlusContext::ShouldOffset() const
1351 if ( !m_pen
.IsNull() )
1353 penwidth
= (int)((wxGDIPlusPenData
*)m_pen
.GetRefData())->GetWidth();
1354 if ( penwidth
== 0 )
1357 return ( penwidth
% 2 ) == 1;
1360 void* wxGDIPlusContext::GetNativeContext()
1365 // concatenates this transform with the current transform of this context
1366 void wxGDIPlusContext::ConcatTransform( const wxGraphicsMatrix
& matrix
)
1368 m_context
->MultiplyTransform((Matrix
*) matrix
.GetNativeMatrix());
1371 // sets the transform of this context
1372 void wxGDIPlusContext::SetTransform( const wxGraphicsMatrix
& matrix
)
1374 m_context
->SetTransform((Matrix
*) matrix
.GetNativeMatrix());
1377 // gets the matrix of this context
1378 wxGraphicsMatrix
wxGDIPlusContext::GetTransform() const
1380 wxGraphicsMatrix matrix
= CreateMatrix();
1381 m_context
->GetTransform((Matrix
*) matrix
.GetNativeMatrix());
1384 //-----------------------------------------------------------------------------
1385 // wxGDIPlusRenderer declaration
1386 //-----------------------------------------------------------------------------
1388 class wxGDIPlusRenderer
: public wxGraphicsRenderer
1397 virtual ~wxGDIPlusRenderer()
1407 virtual wxGraphicsContext
* CreateContext( const wxWindowDC
& dc
);
1409 virtual wxGraphicsContext
* CreateContext( const wxMemoryDC
& dc
);
1411 virtual wxGraphicsContext
* CreateContextFromNativeContext( void * context
);
1413 virtual wxGraphicsContext
* CreateContextFromNativeWindow( void * window
);
1415 virtual wxGraphicsContext
* CreateContext( wxWindow
* window
);
1417 virtual wxGraphicsContext
* CreateMeasuringContext();
1421 virtual wxGraphicsPath
CreatePath();
1425 virtual wxGraphicsMatrix
CreateMatrix( wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
1426 wxDouble tx
=0.0, wxDouble ty
=0.0);
1429 virtual wxGraphicsPen
CreatePen(const wxPen
& pen
) ;
1431 virtual wxGraphicsBrush
CreateBrush(const wxBrush
& brush
) ;
1433 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
1434 virtual wxGraphicsBrush
CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
1435 const wxColour
&c1
, const wxColour
&c2
) ;
1437 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
1438 // with radius r and color cColor
1439 virtual wxGraphicsBrush
CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
1440 const wxColour
&oColor
, const wxColour
&cColor
) ;
1443 virtual wxGraphicsFont
CreateFont( const wxFont
&font
, const wxColour
&col
= *wxBLACK
) ;
1445 // create a native bitmap representation
1446 virtual wxGraphicsBitmap
CreateBitmap( const wxBitmap
&bitmap
);
1448 // create a subimage from a native image representation
1449 virtual wxGraphicsBitmap
CreateSubBitmap( const wxGraphicsBitmap
&bitmap
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1452 void EnsureIsLoaded();
1455 friend class wxGDIPlusRendererModule
;
1459 ULONG_PTR m_gditoken
;
1461 DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusRenderer
)
1464 //-----------------------------------------------------------------------------
1465 // wxGDIPlusRenderer implementation
1466 //-----------------------------------------------------------------------------
1468 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusRenderer
,wxGraphicsRenderer
)
1470 static wxGDIPlusRenderer gs_GDIPlusRenderer
;
1472 wxGraphicsRenderer
* wxGraphicsRenderer::GetDefaultRenderer()
1474 return &gs_GDIPlusRenderer
;
1477 void wxGDIPlusRenderer::EnsureIsLoaded()
1485 void wxGDIPlusRenderer::Load()
1487 GdiplusStartupInput input
;
1488 GdiplusStartupOutput output
;
1489 GdiplusStartup(&m_gditoken
,&input
,&output
);
1493 void wxGDIPlusRenderer::Unload()
1497 GdiplusShutdown(m_gditoken
);
1503 wxGraphicsContext
* wxGDIPlusRenderer::CreateContext( const wxWindowDC
& dc
)
1506 wxMSWDCImpl
*msw
= wxDynamicCast( dc
.GetImpl() , wxMSWDCImpl
);
1507 return new wxGDIPlusContext(this,(HDC
) msw
->GetHDC());
1510 wxGraphicsContext
* wxGDIPlusRenderer::CreateContext( const wxMemoryDC
& dc
)
1513 wxMSWDCImpl
*msw
= wxDynamicCast( dc
.GetImpl() , wxMSWDCImpl
);
1514 return new wxGDIPlusContext(this,(HDC
) msw
->GetHDC());
1517 wxGraphicsContext
* wxGDIPlusRenderer::CreateMeasuringContext()
1520 return new wxGDIPlusMeasuringContext(this);
1523 wxGraphicsContext
* wxGDIPlusRenderer::CreateContextFromNativeContext( void * context
)
1526 return new wxGDIPlusContext(this,(Graphics
*) context
);
1530 wxGraphicsContext
* wxGDIPlusRenderer::CreateContextFromNativeWindow( void * window
)
1533 return new wxGDIPlusContext(this,(HWND
) window
);
1536 wxGraphicsContext
* wxGDIPlusRenderer::CreateContext( wxWindow
* window
)
1539 return new wxGDIPlusContext(this, (HWND
) window
->GetHWND() );
1544 wxGraphicsPath
wxGDIPlusRenderer::CreatePath()
1548 m
.SetRefData( new wxGDIPlusPathData(this));
1555 wxGraphicsMatrix
wxGDIPlusRenderer::CreateMatrix( wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
1556 wxDouble tx
, wxDouble ty
)
1561 wxGDIPlusMatrixData
* data
= new wxGDIPlusMatrixData( this );
1562 data
->Set( a
,b
,c
,d
,tx
,ty
) ;
1567 wxGraphicsPen
wxGDIPlusRenderer::CreatePen(const wxPen
& pen
)
1570 if ( !pen
.Ok() || pen
.GetStyle() == wxTRANSPARENT
)
1571 return wxNullGraphicsPen
;
1575 p
.SetRefData(new wxGDIPlusPenData( this, pen
));
1580 wxGraphicsBrush
wxGDIPlusRenderer::CreateBrush(const wxBrush
& brush
)
1583 if ( !brush
.Ok() || brush
.GetStyle() == wxTRANSPARENT
)
1584 return wxNullGraphicsBrush
;
1588 p
.SetRefData(new wxGDIPlusBrushData( this, brush
));
1593 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
1594 wxGraphicsBrush
wxGDIPlusRenderer::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
1595 const wxColour
&c1
, const wxColour
&c2
)
1599 wxGDIPlusBrushData
* d
= new wxGDIPlusBrushData( this );
1600 d
->CreateLinearGradientBrush(x1
, y1
, x2
, y2
, c1
, c2
);
1605 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
1606 // with radius r and color cColor
1607 wxGraphicsBrush
wxGDIPlusRenderer::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
1608 const wxColour
&oColor
, const wxColour
&cColor
)
1612 wxGDIPlusBrushData
* d
= new wxGDIPlusBrushData( this );
1613 d
->CreateRadialGradientBrush(xo
,yo
,xc
,yc
,radius
,oColor
,cColor
);
1619 wxGraphicsFont
wxGDIPlusRenderer::CreateFont( const wxFont
&font
, const wxColour
&col
)
1625 p
.SetRefData(new wxGDIPlusFontData( this , font
, col
));
1629 return wxNullGraphicsFont
;
1632 wxGraphicsBitmap
wxGDIPlusRenderer::CreateBitmap( const wxBitmap
&bitmap
)
1638 p
.SetRefData(new wxGDIPlusBitmapData( this , bitmap
));
1642 return wxNullGraphicsBitmap
;
1645 wxGraphicsBitmap
wxGDIPlusRenderer::CreateSubBitmap( const wxGraphicsBitmap
&bitmap
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1648 Bitmap
* image
= static_cast<wxGDIPlusBitmapData
*>(bitmap
.GetRefData())->GetGDIPlusBitmap();
1652 p
.SetRefData(new wxGDIPlusBitmapData( this , image
->Clone( (REAL
) x
, (REAL
) y
, (REAL
) w
, (REAL
) h
, PixelFormat32bppPARGB
) ));
1656 return wxNullGraphicsBitmap
;
1659 // Shutdown GDI+ at app exit, before possible dll unload
1660 class wxGDIPlusRendererModule
: public wxModule
1663 virtual bool OnInit() { return true; }
1664 virtual void OnExit() { gs_GDIPlusRenderer
.Unload(); }
1667 DECLARE_DYNAMIC_CLASS(wxGDIPlusRendererModule
)
1670 IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusRendererModule
, wxModule
)
1672 #endif // wxUSE_GRAPHICS_CONTEXT