]> git.saurik.com Git - wxWidgets.git/blame - src/msw/graphics.cpp
Don't overwrite status message when restoring it if it changed.
[wxWidgets.git] / src / msw / graphics.cpp
CommitLineData
6fea499c 1/////////////////////////////////////////////////////////////////////////////
e0876d73 2// Name: src/msw/graphics.cpp
6fea499c
SC
3// Purpose: wxGCDC class
4// Author: Stefan Csomor
5// Modified by:
e0876d73 6// Created: 2006-09-30
6fea499c 7// RCS-ID: $Id$
e0876d73 8// Copyright: (c) 2006 Stefan Csomor
6fea499c
SC
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
6fea499c 14#ifdef __BORLANDC__
b4715d08 15 #pragma hdrstop
6fea499c
SC
16#endif
17
b4715d08
VZ
18#include "wx/dc.h"
19
0024ec50
VZ
20#if wxUSE_GRAPHICS_CONTEXT
21
6fea499c 22#ifndef WX_PRECOMP
bdba6fdc
VZ
23 #include "wx/msw/wrapcdlg.h"
24 #include "wx/image.h"
25 #include "wx/window.h"
bdba6fdc
VZ
26 #include "wx/utils.h"
27 #include "wx/dialog.h"
28 #include "wx/app.h"
29 #include "wx/bitmap.h"
bdba6fdc
VZ
30 #include "wx/log.h"
31 #include "wx/icon.h"
bdba6fdc 32 #include "wx/module.h"
f772729b
SC
33 // include all dc types that are used as a param
34 #include "wx/dc.h"
35 #include "wx/dcclient.h"
36 #include "wx/dcmemory.h"
37 #include "wx/dcprint.h"
6fea499c
SC
38#endif
39
623cf1fa 40#include "wx/private/graphics.h"
bdba6fdc 41#include "wx/msw/wrapgdip.h"
bce28872 42#include "wx/msw/dc.h"
6fea499c 43
bdba6fdc 44#include "wx/stack.h"
6fea499c 45
bdba6fdc 46WX_DECLARE_STACK(GraphicsState, GraphicsStates);
0024ec50 47
6fea499c
SC
48//-----------------------------------------------------------------------------
49// constants
50//-----------------------------------------------------------------------------
51
52const double RAD2DEG = 180.0 / M_PI;
53
54//-----------------------------------------------------------------------------
55// Local functions
56//-----------------------------------------------------------------------------
57
58static inline double dmin(double a, double b) { return a < b ? a : b; }
59static inline double dmax(double a, double b) { return a > b ? a : b; }
60
61static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
62static inline double RadToDeg(double deg) { return (deg * 180.0) / M_PI; }
63
64//-----------------------------------------------------------------------------
65// device context implementation
66//
67// more and more of the dc functionality should be implemented by calling
68// the appropricate wxGDIPlusContext, but we will have to do that step by step
69// also coordinate conversions should be moved to native matrix ops
70//-----------------------------------------------------------------------------
71
72// we always stock two context states, one at entry, to be able to preserve the
73// state we were called with, the other one after changing to HI Graphics orientation
74// (this one is used for getting back clippings etc)
75
76//-----------------------------------------------------------------------------
77// wxGraphicsPath implementation
78//-----------------------------------------------------------------------------
79
80#include "wx/msw/private.h" // needs to be before #include <commdlg.h>
81
82#if wxUSE_COMMON_DIALOGS && !defined(__WXMICROWIN__)
83#include <commdlg.h>
84#endif
85
eb4083ef 86class wxGDIPlusPathData : public wxGraphicsPathData
6fea499c 87{
6fea499c 88public :
a4e73390
SC
89 wxGDIPlusPathData(wxGraphicsRenderer* renderer, GraphicsPath* path = NULL);
90 ~wxGDIPlusPathData();
6fea499c 91
a4e73390 92 virtual wxGraphicsObjectRefData *Clone() const;
6fea499c
SC
93
94 //
95 // These are the path primitives from which everything else can be constructed
96 //
97
98 // begins a new subpath at (x,y)
99 virtual void MoveToPoint( wxDouble x, wxDouble y );
100
cb3a0d42 101 // adds a straight line from the current point to (x,y)
6fea499c
SC
102 virtual void AddLineToPoint( wxDouble x, wxDouble y );
103
104 // adds a cubic Bezier curve from the current point, using two control points and an end point
105 virtual void AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y );
106
107
cb3a0d42 108 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
6fea499c
SC
109 virtual void AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise ) ;
110
111 // gets the last point of the current path, (0,0) if not yet set
a4e73390 112 virtual void GetCurrentPoint( wxDouble* x, wxDouble* y) const;
6fea499c 113
83576e68 114 // adds another path
a4e73390 115 virtual void AddPath( const wxGraphicsPathData* path );
83576e68 116
6fea499c
SC
117 // closes the current sub-path
118 virtual void CloseSubpath();
119
120 //
cb3a0d42 121 // These are convenience functions which - if not available natively will be assembled
6fea499c
SC
122 // using the primitives from above
123 //
124
cb3a0d42 125 // appends a rectangle as a new closed subpath
6fea499c
SC
126 virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) ;
127 /*
128
129 // appends an ellipsis as a new closed subpath fitting the passed rectangle
130 virtual void AddEllipsis( wxDouble x, wxDouble y, wxDouble w , wxDouble h ) ;
131
132 // 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)
133 virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r ) ;
134*/
135
cb3a0d42
VZ
136 // returns the native path
137 virtual void * GetNativePath() const { return m_path; }
138
139 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
140 virtual void UnGetNativePath(void * WXUNUSED(path)) const {}
f540e5bd 141
83576e68 142 // transforms each point of this path by the matrix
a4e73390 143 virtual void Transform( const wxGraphicsMatrixData* matrix ) ;
83576e68
SC
144
145 // gets the bounding box enclosing all points (possibly including control points)
a4e73390 146 virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const;
83576e68 147
94a007ec 148 virtual bool Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle = wxODDEVEN_RULE) const;
83576e68 149
6fea499c
SC
150private :
151 GraphicsPath* m_path;
152};
153
eb4083ef 154class wxGDIPlusMatrixData : public wxGraphicsMatrixData
83576e68
SC
155{
156public :
a4e73390
SC
157 wxGDIPlusMatrixData(wxGraphicsRenderer* renderer, Matrix* matrix = NULL) ;
158 virtual ~wxGDIPlusMatrixData() ;
83576e68 159
a4e73390 160 virtual wxGraphicsObjectRefData* Clone() const ;
83576e68
SC
161
162 // concatenates the matrix
a4e73390 163 virtual void Concat( const wxGraphicsMatrixData *t );
83576e68
SC
164
165 // sets the matrix to the respective values
cb3a0d42 166 virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
83576e68
SC
167 wxDouble tx=0.0, wxDouble ty=0.0);
168
248802d0
RD
169 // gets the component valuess of the matrix
170 virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL,
171 wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
f4322df6 172
83576e68
SC
173 // makes this the inverse matrix
174 virtual void Invert();
175
176 // returns true if the elements of the transformation matrix are equal ?
a4e73390 177 virtual bool IsEqual( const wxGraphicsMatrixData* t) const ;
83576e68
SC
178
179 // return true if this is the identity matrix
a4e73390 180 virtual bool IsIdentity() const;
83576e68
SC
181
182 //
183 // transformation
184 //
185
186 // add the translation to this matrix
187 virtual void Translate( wxDouble dx , wxDouble dy );
188
189 // add the scale to this matrix
190 virtual void Scale( wxDouble xScale , wxDouble yScale );
191
192 // add the rotation to this matrix (radians)
cb3a0d42 193 virtual void Rotate( wxDouble angle );
83576e68
SC
194
195 //
196 // apply the transforms
197 //
198
199 // applies that matrix to the point
a4e73390 200 virtual void TransformPoint( wxDouble *x, wxDouble *y ) const;
83576e68
SC
201
202 // applies the matrix except for translations
a4e73390 203 virtual void TransformDistance( wxDouble *dx, wxDouble *dy ) const;
83576e68
SC
204
205 // returns the native representation
206 virtual void * GetNativeMatrix() const;
207private:
208 Matrix* m_matrix ;
83576e68
SC
209} ;
210
eb4083ef 211class wxGDIPlusPenData : public wxGraphicsObjectRefData
83576e68
SC
212{
213public:
2c820406
SC
214 wxGDIPlusPenData( wxGraphicsRenderer* renderer, const wxPen &pen );
215 ~wxGDIPlusPenData();
83576e68
SC
216
217 void Init();
218
83576e68
SC
219 virtual wxDouble GetWidth() { return m_width; }
220 virtual Pen* GetGDIPlusPen() { return m_pen; }
221
222protected :
223 Pen* m_pen;
224 Image* m_penImage;
225 Brush* m_penBrush;
226
227 wxDouble m_width;
83576e68
SC
228};
229
eb4083ef 230class wxGDIPlusBrushData : public wxGraphicsObjectRefData
83576e68
SC
231{
232public:
2c820406
SC
233 wxGDIPlusBrushData( wxGraphicsRenderer* renderer );
234 wxGDIPlusBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush );
235 ~wxGDIPlusBrushData ();
83576e68 236
cb3a0d42 237 void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
83576e68
SC
238 const wxColour&c1, const wxColour&c2 );
239 void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
240 const wxColour &oColor, const wxColour &cColor );
241 virtual Brush* GetGDIPlusBrush() { return m_brush; }
242
243protected:
244 virtual void Init();
245
246private :
247 Brush* m_brush;
248 Image* m_brushImage;
249 GraphicsPath* m_brushPath;
83576e68
SC
250};
251
bce28872
SC
252class WXDLLIMPEXP_CORE wxGDIPlusBitmapData : public wxGraphicsObjectRefData
253{
254public:
255 wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap );
256 wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, const wxBitmap &bmp );
257 ~wxGDIPlusBitmapData ();
258
259 virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; }
260
261private :
262 Bitmap* m_bitmap;
263 Bitmap* m_helper;
264};
265
eb4083ef 266class wxGDIPlusFontData : public wxGraphicsObjectRefData
83576e68
SC
267{
268public:
2c820406
SC
269 wxGDIPlusFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
270 ~wxGDIPlusFontData();
83576e68 271
83576e68
SC
272 virtual Brush* GetGDIPlusBrush() { return m_textBrush; }
273 virtual Font* GetGDIPlusFont() { return m_font; }
274private :
275 Brush* m_textBrush;
276 Font* m_font;
83576e68
SC
277};
278
eb4083ef 279class wxGDIPlusContext : public wxGraphicsContext
6fea499c 280{
6fea499c 281public:
81e0b3d9 282 wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc , wxDouble width, wxDouble height );
83576e68
SC
283 wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd );
284 wxGDIPlusContext( wxGraphicsRenderer* renderer, Graphics* gr);
6fea499c 285 wxGDIPlusContext();
9f339b18 286
6fea499c
SC
287 virtual ~wxGDIPlusContext();
288
289 virtual void Clip( const wxRegion &region );
539e2795
SC
290 // clips drawings to the rect
291 virtual void Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
539e2795 292
cb3a0d42
VZ
293 // resets the clipping to original extent
294 virtual void ResetClip();
295
296 virtual void * GetNativeContext();
297
a4e73390 298 virtual void StrokePath( const wxGraphicsPath& p );
94a007ec 299 virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
6fea499c 300
0c7bd159
SC
301 // stroke lines connecting each of the points
302 virtual void StrokeLines( size_t n, const wxPoint2DDouble *points);
303
304 // draws a polygon
94a007ec 305 virtual void DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
0c7bd159 306
bf02a7f9
SC
307 virtual bool SetAntialiasMode(wxAntialiasMode antialias);
308
309 virtual bool SetCompositionMode(wxCompositionMode op);
310
311 virtual void BeginLayer(wxDouble opacity);
312
313 virtual void EndLayer();
314
cb3a0d42
VZ
315 virtual void Translate( wxDouble dx , wxDouble dy );
316 virtual void Scale( wxDouble xScale , wxDouble yScale );
317 virtual void Rotate( wxDouble angle );
6fea499c 318
83576e68 319 // concatenates this transform with the current transform of this context
a4e73390 320 virtual void ConcatTransform( const wxGraphicsMatrix& matrix );
83576e68
SC
321
322 // sets the transform of this context
a4e73390 323 virtual void SetTransform( const wxGraphicsMatrix& matrix );
83576e68
SC
324
325 // gets the matrix of this context
a4e73390 326 virtual wxGraphicsMatrix GetTransform() const;
83576e68 327
bce28872 328 virtual void DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
6fea499c
SC
329 virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
330 virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
cb3a0d42 331 virtual void PushState();
6fea499c
SC
332 virtual void PopState();
333
6fea499c
SC
334 virtual void GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
335 wxDouble *descent, wxDouble *externalLeading ) const;
336 virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
d9485f89 337 virtual bool ShouldOffset() const;
fbd5416f 338 virtual void GetSize( wxDouble* width, wxDouble *height );
6fea499c
SC
339
340private:
9f339b18
SC
341 void Init();
342 void SetDefaults();
343
0b7dce54
VZ
344 virtual void DoDrawText(const wxString& str, wxDouble x, wxDouble y)
345 { DoDrawFilledText(str, x, y, wxNullGraphicsBrush); }
346 virtual void DoDrawFilledText(const wxString& str, wxDouble x, wxDouble y,
347 const wxGraphicsBrush& backgroundBrush);
348
83576e68 349 Graphics* m_context;
bdba6fdc 350 GraphicsStates m_stateStack;
83576e68
SC
351 GraphicsState m_state1;
352 GraphicsState m_state2;
353
81e0b3d9
SC
354 wxDouble m_width;
355 wxDouble m_height;
356
83576e68
SC
357 DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusContext)
358};
359
5aac6f3f 360class wxGDIPlusMeasuringContext : public wxGDIPlusContext
0c7bd159
SC
361{
362public:
81e0b3d9 363 wxGDIPlusMeasuringContext( wxGraphicsRenderer* renderer ) : wxGDIPlusContext( renderer , m_hdc = GetDC(NULL), 1000, 1000 )
0c7bd159
SC
364 {
365 }
366 wxGDIPlusMeasuringContext()
367 {
368 }
369
370 virtual ~wxGDIPlusMeasuringContext()
371 {
372 ReleaseDC( NULL, m_hdc );
373 }
374
375private:
376 HDC m_hdc ;
377 DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusMeasuringContext)
378} ;
379
83576e68
SC
380//-----------------------------------------------------------------------------
381// wxGDIPlusPen implementation
382//-----------------------------------------------------------------------------
383
2c820406 384wxGDIPlusPenData::~wxGDIPlusPenData()
83576e68
SC
385{
386 delete m_pen;
387 delete m_penImage;
388 delete m_penBrush;
389}
390
2c820406 391void wxGDIPlusPenData::Init()
83576e68
SC
392{
393 m_pen = NULL ;
394 m_penImage = NULL;
395 m_penBrush = NULL;
396}
397
2c820406
SC
398wxGDIPlusPenData::wxGDIPlusPenData( wxGraphicsRenderer* renderer, const wxPen &pen )
399: wxGraphicsObjectRefData(renderer)
cb3a0d42 400{
83576e68
SC
401 Init();
402 m_width = pen.GetWidth();
403 if (m_width <= 0.0)
404 m_width = 0.1;
405
406 m_pen = new Pen(Color( pen.GetColour().Alpha() , pen.GetColour().Red() ,
407 pen.GetColour().Green() , pen.GetColour().Blue() ), m_width );
408
409 LineCap cap;
410 switch ( pen.GetCap() )
411 {
412 case wxCAP_ROUND :
413 cap = LineCapRound;
414 break;
415
416 case wxCAP_PROJECTING :
417 cap = LineCapSquare;
418 break;
419
420 case wxCAP_BUTT :
421 cap = LineCapFlat; // TODO verify
422 break;
423
424 default :
425 cap = LineCapFlat;
426 break;
427 }
428 m_pen->SetLineCap(cap,cap, DashCapFlat);
429
430 LineJoin join;
431 switch ( pen.GetJoin() )
432 {
433 case wxJOIN_BEVEL :
434 join = LineJoinBevel;
435 break;
436
437 case wxJOIN_MITER :
438 join = LineJoinMiter;
439 break;
440
441 case wxJOIN_ROUND :
442 join = LineJoinRound;
443 break;
444
445 default :
446 join = LineJoinMiter;
447 break;
448 }
449
450 m_pen->SetLineJoin(join);
451
452 m_pen->SetDashStyle(DashStyleSolid);
453
454 DashStyle dashStyle = DashStyleSolid;
455 switch ( pen.GetStyle() )
456 {
457 case wxSOLID :
458 break;
459
460 case wxDOT :
461 dashStyle = DashStyleDot;
462 break;
463
464 case wxLONG_DASH :
465 dashStyle = DashStyleDash; // TODO verify
466 break;
467
468 case wxSHORT_DASH :
469 dashStyle = DashStyleDash;
470 break;
471
472 case wxDOT_DASH :
473 dashStyle = DashStyleDashDot;
474 break;
475 case wxUSER_DASH :
476 {
477 dashStyle = DashStyleCustom;
478 wxDash *dashes;
479 int count = pen.GetDashes( &dashes );
480 if ((dashes != NULL) && (count > 0))
481 {
482 REAL *userLengths = new REAL[count];
483 for ( int i = 0; i < count; ++i )
484 {
485 userLengths[i] = dashes[i];
486 }
487 m_pen->SetDashPattern( userLengths, count);
488 delete[] userLengths;
489 }
490 }
491 break;
492 case wxSTIPPLE :
493 {
494 wxBitmap* bmp = pen.GetStipple();
495 if ( bmp && bmp->Ok() )
496 {
497 m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE());
498 m_penBrush = new TextureBrush(m_penImage);
499 m_pen->SetBrush( m_penBrush );
500 }
501
502 }
503 break;
504 default :
505 if ( pen.GetStyle() >= wxFIRST_HATCH && pen.GetStyle() <= wxLAST_HATCH )
506 {
507 HatchStyle style = HatchStyleHorizontal;
508 switch( pen.GetStyle() )
509 {
510 case wxBDIAGONAL_HATCH :
511 style = HatchStyleBackwardDiagonal;
512 break ;
513 case wxCROSSDIAG_HATCH :
514 style = HatchStyleDiagonalCross;
515 break ;
516 case wxFDIAGONAL_HATCH :
517 style = HatchStyleForwardDiagonal;
518 break ;
519 case wxCROSS_HATCH :
520 style = HatchStyleCross;
521 break ;
522 case wxHORIZONTAL_HATCH :
523 style = HatchStyleHorizontal;
524 break ;
525 case wxVERTICAL_HATCH :
526 style = HatchStyleVertical;
527 break ;
528
529 }
530 m_penBrush = new HatchBrush(style,Color( pen.GetColour().Alpha() , pen.GetColour().Red() ,
531 pen.GetColour().Green() , pen.GetColour().Blue() ), Color::Transparent );
532 m_pen->SetBrush( m_penBrush );
533 }
534 break;
cb3a0d42 535 }
83576e68
SC
536 if ( dashStyle != DashStyleSolid )
537 m_pen->SetDashStyle(dashStyle);
538}
539
83576e68
SC
540//-----------------------------------------------------------------------------
541// wxGDIPlusBrush implementation
542//-----------------------------------------------------------------------------
543
2c820406
SC
544wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer* renderer )
545: wxGraphicsObjectRefData(renderer)
83576e68
SC
546{
547 Init();
548}
549
2c820406
SC
550wxGDIPlusBrushData::wxGDIPlusBrushData( wxGraphicsRenderer* renderer , const wxBrush &brush )
551: wxGraphicsObjectRefData(renderer)
83576e68
SC
552{
553 Init();
554 if ( brush.GetStyle() == wxSOLID)
555 {
556 m_brush = new SolidBrush( Color( brush.GetColour().Alpha() , brush.GetColour().Red() ,
557 brush.GetColour().Green() , brush.GetColour().Blue() ) );
558 }
559 else if ( brush.IsHatch() )
560 {
561 HatchStyle style = HatchStyleHorizontal;
562 switch( brush.GetStyle() )
563 {
564 case wxBDIAGONAL_HATCH :
565 style = HatchStyleBackwardDiagonal;
566 break ;
567 case wxCROSSDIAG_HATCH :
568 style = HatchStyleDiagonalCross;
569 break ;
570 case wxFDIAGONAL_HATCH :
571 style = HatchStyleForwardDiagonal;
572 break ;
573 case wxCROSS_HATCH :
574 style = HatchStyleCross;
575 break ;
576 case wxHORIZONTAL_HATCH :
577 style = HatchStyleHorizontal;
578 break ;
579 case wxVERTICAL_HATCH :
580 style = HatchStyleVertical;
581 break ;
582
583 }
584 m_brush = new HatchBrush(style,Color( brush.GetColour().Alpha() , brush.GetColour().Red() ,
585 brush.GetColour().Green() , brush.GetColour().Blue() ), Color::Transparent );
586 }
cb3a0d42 587 else
83576e68
SC
588 {
589 wxBitmap* bmp = brush.GetStipple();
590 if ( bmp && bmp->Ok() )
591 {
592 wxDELETE( m_brushImage );
593 m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE());
594 m_brush = new TextureBrush(m_brushImage);
595 }
596 }
597}
598
2c820406 599wxGDIPlusBrushData::~wxGDIPlusBrushData()
83576e68
SC
600{
601 delete m_brush;
602 delete m_brushImage;
603 delete m_brushPath;
604};
605
2c820406 606void wxGDIPlusBrushData::Init()
83576e68
SC
607{
608 m_brush = NULL;
609 m_brushImage= NULL;
610 m_brushPath= NULL;
611}
612
cb3a0d42 613void wxGDIPlusBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, const wxColour&c1, const wxColour&c2)
83576e68
SC
614{
615 m_brush = new LinearGradientBrush( PointF( x1,y1) , PointF( x2,y2),
616 Color( c1.Alpha(), c1.Red(),c1.Green() , c1.Blue() ),
617 Color( c2.Alpha(), c2.Red(),c2.Green() , c2.Blue() ));
618}
619
2c820406 620void wxGDIPlusBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
83576e68
SC
621 const wxColour &oColor, const wxColour &cColor)
622{
623 // Create a path that consists of a single circle.
624 m_brushPath = new GraphicsPath();
625 m_brushPath->AddEllipse( (REAL)(xc-radius), (REAL)(yc-radius), (REAL)(2*radius), (REAL)(2*radius));
626
627 PathGradientBrush *b = new PathGradientBrush(m_brushPath);
628 m_brush = b;
629 b->SetCenterPoint( PointF(xo,yo));
630 b->SetCenterColor(Color( oColor.Alpha(), oColor.Red(),oColor.Green() , oColor.Blue() ));
631
632 Color colors[] = {Color( cColor.Alpha(), cColor.Red(),cColor.Green() , cColor.Blue() )};
633 int count = 1;
634 b->SetSurroundColors(colors, &count);
635}
636
83576e68
SC
637//-----------------------------------------------------------------------------
638// wxGDIPlusFont implementation
639//-----------------------------------------------------------------------------
640
cb3a0d42 641wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer, const wxFont &font,
2c820406 642 const wxColour& col ) : wxGraphicsObjectRefData( renderer )
83576e68
SC
643{
644 m_textBrush = NULL;
645 m_font = NULL;
646
647 wxWCharBuffer s = font.GetFaceName().wc_str( *wxConvUI );
648 int size = font.GetPointSize();
649 int style = FontStyleRegular;
650 if ( font.GetStyle() == wxFONTSTYLE_ITALIC )
651 style |= FontStyleItalic;
652 if ( font.GetUnderlined() )
653 style |= FontStyleUnderline;
654 if ( font.GetWeight() == wxFONTWEIGHT_BOLD )
655 style |= FontStyleBold;
656 m_font = new Font( s , size , style );
657 m_textBrush = new SolidBrush( Color( col.Alpha() , col.Red() ,
658 col.Green() , col.Blue() ));
659}
6fea499c 660
2c820406 661wxGDIPlusFontData::~wxGDIPlusFontData()
83576e68
SC
662{
663 delete m_textBrush;
664 delete m_font;
665}
6fea499c 666
bce28872
SC
667// the built-in conversions functions create non-premultiplied bitmaps, while GDIPlus needs them in the
668// premultiplied format, therefore in the failing cases we create a new bitmap using the non-premultiplied
669// bytes as parameter, since there is no real copying of the data going in, only references are stored
670// m_helper has to be kept alive as well
671
672//-----------------------------------------------------------------------------
673// wxGDIPlusBitmapData implementation
674//-----------------------------------------------------------------------------
675
676wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap ) :
677 wxGraphicsObjectRefData( renderer ), m_bitmap( bitmap )
678{
679 m_helper = NULL;
680}
681
0b7dce54 682wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer,
bce28872
SC
683 const wxBitmap &bmp) : wxGraphicsObjectRefData( renderer )
684{
685 m_bitmap = NULL;
686 m_helper = NULL;
687
688 Bitmap* image = NULL;
689 if ( bmp.GetMask() )
690 {
691 Bitmap interim((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE()) ;
692
693 size_t width = interim.GetWidth();
694 size_t height = interim.GetHeight();
695 Rect bounds(0,0,width,height);
696
697 image = new Bitmap(width,height,PixelFormat32bppPARGB) ;
698
699 Bitmap interimMask((HBITMAP)bmp.GetMask()->GetMaskBitmap(),NULL);
700 wxASSERT(interimMask.GetPixelFormat() == PixelFormat1bppIndexed);
701
702 BitmapData dataMask ;
703 interimMask.LockBits(&bounds,ImageLockModeRead,
704 interimMask.GetPixelFormat(),&dataMask);
705
706
707 BitmapData imageData ;
708 image->LockBits(&bounds,ImageLockModeWrite, PixelFormat32bppPARGB, &imageData);
709
710 BYTE maskPattern = 0 ;
711 BYTE maskByte = 0;
712 size_t maskIndex ;
713
714 for ( size_t y = 0 ; y < height ; ++y)
715 {
716 maskIndex = 0 ;
717 for( size_t x = 0 ; x < width; ++x)
718 {
719 if ( x % 8 == 0)
720 {
721 maskPattern = 0x80;
722 maskByte = *((BYTE*)dataMask.Scan0 + dataMask.Stride*y + maskIndex);
723 maskIndex++;
724 }
725 else
726 maskPattern = maskPattern >> 1;
727
728 ARGB *dest = (ARGB*)((BYTE*)imageData.Scan0 + imageData.Stride*y + x*4);
729 if ( (maskByte & maskPattern) == 0 )
730 *dest = 0x00000000;
731 else
732 {
733 Color c ;
734 interim.GetPixel(x,y,&c) ;
735 *dest = (c.GetValue() | Color::AlphaMask);
736 }
737 }
738 }
739
740 image->UnlockBits(&imageData);
741
742 interimMask.UnlockBits(&dataMask);
743 interim.UnlockBits(&dataMask);
744 }
745 else
746 {
747 image = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE());
748 if ( bmp.HasAlpha() && GetPixelFormatSize(image->GetPixelFormat()) == 32 )
749 {
750 size_t width = image->GetWidth();
751 size_t height = image->GetHeight();
752 Rect bounds(0,0,width,height);
753 static BitmapData data ;
754
755 m_helper = image ;
756 image = NULL ;
757 m_helper->LockBits(&bounds, ImageLockModeRead,
758 m_helper->GetPixelFormat(),&data);
759
760 image = new Bitmap(data.Width, data.Height, data.Stride,
761 PixelFormat32bppPARGB , (BYTE*) data.Scan0);
762
763 m_helper->UnlockBits(&data);
764 }
765 }
766 if ( image )
767 m_bitmap = image;
768}
769
770wxGDIPlusBitmapData::~wxGDIPlusBitmapData()
771{
772 delete m_bitmap;
773 delete m_helper;
774}
775
83576e68
SC
776//-----------------------------------------------------------------------------
777// wxGDIPlusPath implementation
778//-----------------------------------------------------------------------------
6fea499c 779
a4e73390 780wxGDIPlusPathData::wxGDIPlusPathData(wxGraphicsRenderer* renderer, GraphicsPath* path ) : wxGraphicsPathData(renderer)
83576e68
SC
781{
782 if ( path )
783 m_path = path;
784 else
785 m_path = new GraphicsPath();
786}
787
a4e73390 788wxGDIPlusPathData::~wxGDIPlusPathData()
6fea499c
SC
789{
790 delete m_path;
791}
792
a4e73390 793wxGraphicsObjectRefData* wxGDIPlusPathData::Clone() const
83576e68 794{
a4e73390 795 return new wxGDIPlusPathData( GetRenderer() , m_path->Clone());
83576e68
SC
796}
797
6fea499c
SC
798//
799// The Primitives
800//
801
a4e73390 802void wxGDIPlusPathData::MoveToPoint( wxDouble x , wxDouble y )
6fea499c
SC
803{
804 m_path->StartFigure();
805 m_path->AddLine((REAL) x,(REAL) y,(REAL) x,(REAL) y);
806}
807
a4e73390 808void wxGDIPlusPathData::AddLineToPoint( wxDouble x , wxDouble y )
6fea499c
SC
809{
810 m_path->AddLine((REAL) x,(REAL) y,(REAL) x,(REAL) y);
811}
812
a4e73390 813void wxGDIPlusPathData::CloseSubpath()
6fea499c
SC
814{
815 m_path->CloseFigure();
816}
817
a4e73390 818void wxGDIPlusPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
6fea499c
SC
819{
820 PointF c1(cx1,cy1);
821 PointF c2(cx2,cy2);
822 PointF end(x,y);
823 PointF start;
824 m_path->GetLastPoint(&start);
825 m_path->AddBezier(start,c1,c2,end);
826}
827
828// gets the last point of the current path, (0,0) if not yet set
a4e73390 829void wxGDIPlusPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
6fea499c
SC
830{
831 PointF start;
832 m_path->GetLastPoint(&start);
a4e73390
SC
833 *x = start.X ;
834 *y = start.Y ;
6fea499c
SC
835}
836
cb3a0d42 837void wxGDIPlusPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, double startAngle, double endAngle, bool clockwise )
6fea499c
SC
838{
839 double sweepAngle = endAngle - startAngle ;
c5b8c66a 840 if( fabs(sweepAngle) >= 2*M_PI)
6fea499c
SC
841 {
842 sweepAngle = 2 * M_PI;
843 }
844 else
845 {
846 if ( clockwise )
847 {
848 if( sweepAngle < 0 )
849 sweepAngle += 2 * M_PI;
850 }
851 else
852 {
853 if( sweepAngle > 0 )
854 sweepAngle -= 2 * M_PI;
855
856 }
857 }
cb3a0d42 858 m_path->AddArc((REAL) (x-r),(REAL) (y-r),(REAL) (2*r),(REAL) (2*r),RadToDeg(startAngle),RadToDeg(sweepAngle));
6fea499c
SC
859}
860
a4e73390 861void wxGDIPlusPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
6fea499c
SC
862{
863 m_path->AddRectangle(RectF(x,y,w,h));
864}
865
a4e73390 866void wxGDIPlusPathData::AddPath( const wxGraphicsPathData* path )
6fea499c 867{
83576e68 868 m_path->AddPath( (GraphicsPath*) path->GetNativePath(), FALSE);
6fea499c
SC
869}
870
6fea499c 871
83576e68 872// transforms each point of this path by the matrix
cb3a0d42 873void wxGDIPlusPathData::Transform( const wxGraphicsMatrixData* matrix )
9f339b18 874{
83576e68 875 m_path->Transform( (Matrix*) matrix->GetNativeMatrix() );
9f339b18 876}
6fea499c 877
83576e68 878// gets the bounding box enclosing all points (possibly including control points)
a4e73390 879void wxGDIPlusPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const
e49c065d 880{
83576e68
SC
881 RectF bounds;
882 m_path->GetBounds( &bounds, NULL, NULL) ;
883 *x = bounds.X;
884 *y = bounds.Y;
885 *w = bounds.Width;
886 *h = bounds.Height;
e49c065d
RD
887}
888
94a007ec 889bool wxGDIPlusPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle ) const
6fea499c 890{
83576e68
SC
891 m_path->SetFillMode( fillStyle == wxODDEVEN_RULE ? FillModeAlternate : FillModeWinding);
892 return m_path->IsVisible( (FLOAT) x,(FLOAT) y) == TRUE ;
893}
9f339b18 894
83576e68 895//-----------------------------------------------------------------------------
a4e73390 896// wxGDIPlusMatrixData implementation
83576e68 897//-----------------------------------------------------------------------------
9f339b18 898
a4e73390
SC
899wxGDIPlusMatrixData::wxGDIPlusMatrixData(wxGraphicsRenderer* renderer, Matrix* matrix )
900 : wxGraphicsMatrixData(renderer)
9f339b18 901{
83576e68
SC
902 if ( matrix )
903 m_matrix = matrix ;
904 else
905 m_matrix = new Matrix();
6fea499c
SC
906}
907
cb3a0d42 908wxGDIPlusMatrixData::~wxGDIPlusMatrixData()
6fea499c 909{
83576e68 910 delete m_matrix;
6fea499c
SC
911}
912
cb3a0d42 913wxGraphicsObjectRefData *wxGDIPlusMatrixData::Clone() const
6fea499c 914{
a4e73390 915 return new wxGDIPlusMatrixData( GetRenderer(), m_matrix->Clone());
539e2795
SC
916}
917
83576e68 918// concatenates the matrix
a4e73390 919void wxGDIPlusMatrixData::Concat( const wxGraphicsMatrixData *t )
539e2795 920{
83576e68 921 m_matrix->Multiply( (Matrix*) t->GetNativeMatrix());
539e2795 922}
83576e68 923
83576e68 924// sets the matrix to the respective values
cb3a0d42 925void wxGDIPlusMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
83576e68 926 wxDouble tx, wxDouble ty)
6fea499c 927{
83576e68 928 m_matrix->SetElements(a,b,c,d,tx,ty);
6fea499c
SC
929}
930
248802d0
RD
931// gets the component valuess of the matrix
932void wxGDIPlusMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
933 wxDouble* d, wxDouble* tx, wxDouble* ty) const
934{
935 REAL elements[6];
936 m_matrix->GetElements(elements);
937 if (a) *a = elements[0];
938 if (b) *b = elements[1];
939 if (c) *c = elements[2];
940 if (d) *d = elements[3];
941 if (tx) *tx= elements[4];
942 if (ty) *ty= elements[5];
943}
944
83576e68 945// makes this the inverse matrix
a4e73390 946void wxGDIPlusMatrixData::Invert()
6fea499c 947{
83576e68 948 m_matrix->Invert();
6fea499c
SC
949}
950
83576e68 951// returns true if the elements of the transformation matrix are equal ?
cb3a0d42 952bool wxGDIPlusMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
6fea499c 953{
83576e68 954 return m_matrix->Equals((Matrix*) t->GetNativeMatrix())== TRUE ;
6fea499c
SC
955}
956
83576e68 957// return true if this is the identity matrix
a4e73390 958bool wxGDIPlusMatrixData::IsIdentity() const
6fea499c 959{
83576e68 960 return m_matrix->IsIdentity() == TRUE ;
6fea499c
SC
961}
962
83576e68
SC
963//
964// transformation
965//
966
967// add the translation to this matrix
a4e73390 968void wxGDIPlusMatrixData::Translate( wxDouble dx , wxDouble dy )
6fea499c 969{
83576e68 970 m_matrix->Translate(dx,dy);
6fea499c
SC
971}
972
83576e68 973// add the scale to this matrix
a4e73390 974void wxGDIPlusMatrixData::Scale( wxDouble xScale , wxDouble yScale )
6fea499c 975{
83576e68 976 m_matrix->Scale(xScale,yScale);
6fea499c
SC
977}
978
83576e68 979// add the rotation to this matrix (radians)
a4e73390 980void wxGDIPlusMatrixData::Rotate( wxDouble angle )
6fea499c 981{
83576e68 982 m_matrix->Rotate( angle );
6fea499c
SC
983}
984
83576e68
SC
985//
986// apply the transforms
987//
988
989// applies that matrix to the point
a4e73390 990void wxGDIPlusMatrixData::TransformPoint( wxDouble *x, wxDouble *y ) const
6fea499c 991{
83576e68
SC
992 PointF pt(*x,*y);
993 m_matrix->TransformPoints(&pt);
994 *x = pt.X;
995 *y = pt.Y;
6fea499c
SC
996}
997
83576e68 998// applies the matrix except for translations
a4e73390 999void wxGDIPlusMatrixData::TransformDistance( wxDouble *dx, wxDouble *dy ) const
6fea499c 1000{
83576e68
SC
1001 PointF pt(*dx,*dy);
1002 m_matrix->TransformVectors(&pt);
1003 *dx = pt.X;
1004 *dy = pt.Y;
6fea499c
SC
1005}
1006
83576e68 1007// returns the native representation
a4e73390 1008void * wxGDIPlusMatrixData::GetNativeMatrix() const
6fea499c 1009{
83576e68
SC
1010 return m_matrix;
1011}
6fea499c 1012
83576e68
SC
1013//-----------------------------------------------------------------------------
1014// wxGDIPlusContext implementation
1015//-----------------------------------------------------------------------------
1016
1017IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusContext,wxGraphicsContext)
0c7bd159
SC
1018IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusMeasuringContext,wxGDIPlusContext)
1019
1020class wxGDIPlusOffsetHelper
1021{
1022public :
1023 wxGDIPlusOffsetHelper( Graphics* gr , bool offset )
1024 {
1025 m_gr = gr;
1026 m_offset = offset;
1027 if ( m_offset )
1028 m_gr->TranslateTransform( 0.5, 0.5 );
1029 }
1030 ~wxGDIPlusOffsetHelper( )
1031 {
1032 if ( m_offset )
1033 m_gr->TranslateTransform( -0.5, -0.5 );
1034 }
1035public :
1036 Graphics* m_gr;
1037 bool m_offset;
1038} ;
83576e68 1039
81e0b3d9 1040wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc, wxDouble width, wxDouble height )
83576e68
SC
1041 : wxGraphicsContext(renderer)
1042{
1043 Init();
1044 m_context = new Graphics( hdc);
81e0b3d9
SC
1045 m_width = width;
1046 m_height = height;
83576e68 1047 SetDefaults();
6fea499c
SC
1048}
1049
83576e68
SC
1050wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd )
1051 : wxGraphicsContext(renderer)
6fea499c 1052{
83576e68
SC
1053 Init();
1054 m_context = new Graphics( hwnd);
81e0b3d9
SC
1055 RECT rect = wxGetWindowRect(hwnd);
1056 m_width = rect.right - rect.left;
1057 m_height = rect.bottom - rect.top;
83576e68
SC
1058 SetDefaults();
1059}
6fea499c 1060
83576e68
SC
1061wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, Graphics* gr )
1062 : wxGraphicsContext(renderer)
1063{
1064 Init();
1065 m_context = gr;
1066 SetDefaults();
1067}
6fea499c 1068
83576e68
SC
1069wxGDIPlusContext::wxGDIPlusContext() : wxGraphicsContext(NULL)
1070{
1071 Init();
1072}
6fea499c 1073
83576e68
SC
1074void wxGDIPlusContext::Init()
1075{
1076 m_context = NULL;
1077 m_state1 = 0;
1078 m_state2= 0;
81e0b3d9
SC
1079 m_height = 0;
1080 m_width = 0;
83576e68 1081}
6fea499c 1082
83576e68
SC
1083void wxGDIPlusContext::SetDefaults()
1084{
0c7bd159
SC
1085 m_context->SetTextRenderingHint(TextRenderingHintSystemDefault);
1086 m_context->SetPixelOffsetMode(PixelOffsetModeHalf);
83576e68
SC
1087 m_context->SetSmoothingMode(SmoothingModeHighQuality);
1088 m_state1 = m_context->Save();
1089 m_state2 = m_context->Save();
1090}
6fea499c 1091
83576e68
SC
1092wxGDIPlusContext::~wxGDIPlusContext()
1093{
83576e68 1094 if ( m_context )
6fea499c 1095 {
83576e68
SC
1096 m_context->Restore( m_state2 );
1097 m_context->Restore( m_state1 );
1098 delete m_context;
6fea499c
SC
1099 }
1100}
1101
83576e68
SC
1102
1103void wxGDIPlusContext::Clip( const wxRegion &region )
6fea499c 1104{
93f72bae
SC
1105 Region rgn((HRGN)region.GetHRGN());
1106 m_context->SetClip(&rgn,CombineModeIntersect);
83576e68 1107}
6fea499c 1108
83576e68
SC
1109void wxGDIPlusContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1110{
1111 m_context->SetClip(RectF(x,y,w,h),CombineModeIntersect);
1112}
cb3a0d42 1113
83576e68
SC
1114void wxGDIPlusContext::ResetClip()
1115{
1116 m_context->ResetClip();
1117}
6fea499c 1118
0c7bd159
SC
1119void wxGDIPlusContext::StrokeLines( size_t n, const wxPoint2DDouble *points)
1120{
bf02a7f9
SC
1121 if (m_composition == wxCOMPOSITION_DEST)
1122 return;
1123
0c7bd159
SC
1124 if ( !m_pen.IsNull() )
1125 {
1126 wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
1127 Point *cpoints = new Point[n];
1128 for (size_t i = 0; i < n; i++)
1129 {
1130 cpoints[i].X = (int)(points[i].m_x );
1131 cpoints[i].Y = (int)(points[i].m_y );
1132
1133 } // for (size_t i = 0; i < n; i++)
1134 m_context->DrawLines( ((wxGDIPlusPenData*)m_pen.GetGraphicsData())->GetGDIPlusPen() , cpoints , n ) ;
1135 delete[] cpoints;
1136 }
1137}
1138
94a007ec 1139void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode WXUNUSED(fillStyle) )
0c7bd159 1140{
bf02a7f9
SC
1141 if (m_composition == wxCOMPOSITION_DEST)
1142 return;
1143
0c7bd159
SC
1144 wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
1145 Point *cpoints = new Point[n];
1146 for (size_t i = 0; i < n; i++)
1147 {
1148 cpoints[i].X = (int)(points[i].m_x );
1149 cpoints[i].Y = (int)(points[i].m_y );
1150
1151 } // for (int i = 0; i < n; i++)
1152 if ( !m_brush.IsNull() )
1153 m_context->FillPolygon( ((wxGDIPlusBrushData*)m_brush.GetRefData())->GetGDIPlusBrush() , cpoints , n ) ;
1154 if ( !m_pen.IsNull() )
1155 m_context->DrawLines( ((wxGDIPlusPenData*)m_pen.GetGraphicsData())->GetGDIPlusPen() , cpoints , n ) ;
1156 delete[] cpoints;
1157}
1158
a4e73390 1159void wxGDIPlusContext::StrokePath( const wxGraphicsPath& path )
83576e68 1160{
bf02a7f9
SC
1161 if (m_composition == wxCOMPOSITION_DEST)
1162 return;
1163
2c820406 1164 if ( !m_pen.IsNull() )
83576e68 1165 {
0c7bd159 1166 wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
a4e73390 1167 m_context->DrawPath( ((wxGDIPlusPenData*)m_pen.GetGraphicsData())->GetGDIPlusPen() , (GraphicsPath*) path.GetNativePath() );
83576e68 1168 }
6fea499c
SC
1169}
1170
94a007ec 1171void wxGDIPlusContext::FillPath( const wxGraphicsPath& path , wxPolygonFillMode fillStyle )
6fea499c 1172{
bf02a7f9
SC
1173 if (m_composition == wxCOMPOSITION_DEST)
1174 return;
1175
2c820406 1176 if ( !m_brush.IsNull() )
83576e68 1177 {
0c7bd159 1178 wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
a4e73390 1179 ((GraphicsPath*) path.GetNativePath())->SetFillMode( fillStyle == wxODDEVEN_RULE ? FillModeAlternate : FillModeWinding);
cb3a0d42 1180 m_context->FillPath( ((wxGDIPlusBrushData*)m_brush.GetRefData())->GetGDIPlusBrush() ,
a4e73390 1181 (GraphicsPath*) path.GetNativePath());
83576e68
SC
1182 }
1183}
6fea499c 1184
bf02a7f9
SC
1185bool wxGDIPlusContext::SetAntialiasMode(wxAntialiasMode antialias)
1186{
1187 if (m_antialias == antialias)
1188 return true;
1189
1190 m_antialias = antialias;
1191
1192 SmoothingMode antialiasMode;
1193 switch (antialias)
1194 {
1195 case wxANTIALIAS_DEFAULT:
1196 antialiasMode = SmoothingModeHighQuality;
1197 break;
1198 case wxANTIALIAS_NONE:
1199 antialiasMode = SmoothingModeNone;
1200 break;
1201 default:
1202 return false;
1203 }
1204 m_context->SetSmoothingMode(antialiasMode);
1205 return true;
1206}
1207
1208bool wxGDIPlusContext::SetCompositionMode(wxCompositionMode op)
1209{
1210 if ( m_composition == op )
1211 return true;
1212
1213 m_composition = op;
1214
1215 if (m_composition == wxCOMPOSITION_DEST)
1216 return true;
1217
1218 CompositingMode cop;
1219 switch (op)
1220 {
1221 case wxCOMPOSITION_SOURCE:
1222 cop = CompositingModeSourceCopy;
1223 break;
1224 case wxCOMPOSITION_OVER:
1225 cop = CompositingModeSourceOver;
1226 break;
1227 default:
1228 return false;
1229 }
1230
1231 m_context->SetCompositingMode(cop);
1232 return true;
1233}
1234
c496d8fa 1235void wxGDIPlusContext::BeginLayer(wxDouble /* opacity */)
bf02a7f9
SC
1236{
1237 // TODO
1238}
1239
1240void wxGDIPlusContext::EndLayer()
1241{
1242 // TODO
1243}
1244
cb3a0d42 1245void wxGDIPlusContext::Rotate( wxDouble angle )
83576e68
SC
1246{
1247 m_context->RotateTransform( RadToDeg(angle) );
1248}
6fea499c 1249
cb3a0d42 1250void wxGDIPlusContext::Translate( wxDouble dx , wxDouble dy )
83576e68
SC
1251{
1252 m_context->TranslateTransform( dx , dy );
1253}
6fea499c 1254
83576e68
SC
1255void wxGDIPlusContext::Scale( wxDouble xScale , wxDouble yScale )
1256{
1257 m_context->ScaleTransform(xScale,yScale);
1258}
6fea499c 1259
83576e68
SC
1260void wxGDIPlusContext::PushState()
1261{
1262 GraphicsState state = m_context->Save();
bdba6fdc 1263 m_stateStack.push(state);
83576e68
SC
1264}
1265
cb3a0d42 1266void wxGDIPlusContext::PopState()
83576e68 1267{
bdba6fdc
VZ
1268 GraphicsState state = m_stateStack.top();
1269 m_stateStack.pop();
83576e68 1270 m_context->Restore(state);
6fea499c
SC
1271}
1272
bce28872 1273void wxGDIPlusContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
6fea499c 1274{
bf02a7f9
SC
1275 if (m_composition == wxCOMPOSITION_DEST)
1276 return;
1277
bce28872
SC
1278 Bitmap* image = static_cast<wxGDIPlusBitmapData*>(bmp.GetRefData())->GetGDIPlusBitmap();
1279 if ( image )
cb3a0d42 1280 {
bce28872 1281 if( image->GetWidth() != (UINT) w || image->GetHeight() != (UINT) h )
fe31db81 1282 {
bce28872
SC
1283 Rect drawRect((REAL) x, (REAL)y, (REAL)w, (REAL)h);
1284 m_context->SetPixelOffsetMode( PixelOffsetModeNone );
1285 m_context->DrawImage(image, drawRect, 0 , 0 , image->GetWidth()-1, image->GetHeight()-1, UnitPixel ) ;
1286 m_context->SetPixelOffsetMode( PixelOffsetModeHalf );
fe31db81 1287 }
bce28872
SC
1288 else
1289 m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ;
fe31db81 1290 }
bce28872 1291}
fe31db81 1292
bce28872
SC
1293void wxGDIPlusContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1294{
1295 wxGraphicsBitmap bitmap = GetRenderer()->CreateBitmap(bmp);
1296 DrawBitmap(bitmap, x, y, w, h);
6fea499c
SC
1297}
1298
cb3a0d42 1299void wxGDIPlusContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
6fea499c 1300{
bf02a7f9
SC
1301 if (m_composition == wxCOMPOSITION_DEST)
1302 return;
1303
0c7bd159
SC
1304 // the built-in conversion fails when there is alpha in the HICON (eg XP style icons), we can only
1305 // find out by looking at the bitmap data whether there really was alpha in it
fe31db81
SC
1306 HICON hIcon = (HICON)icon.GetHICON();
1307 ICONINFO iconInfo ;
1308 // IconInfo creates the bitmaps for color and mask, we must dispose of them after use
1309 if (!GetIconInfo(hIcon,&iconInfo))
1310 return;
1311
fe31db81
SC
1312 Bitmap interim(iconInfo.hbmColor,NULL);
1313
1314 Bitmap* image = NULL ;
1315
0c7bd159
SC
1316 // if it's not 32 bit, it doesn't have an alpha channel, note that since the conversion doesn't
1317 // work correctly, asking IsAlphaPixelFormat at this point fails as well
fe31db81
SC
1318 if( GetPixelFormatSize(interim.GetPixelFormat())!= 32 )
1319 {
1320 image = Bitmap::FromHICON(hIcon);
1321 }
1322 else
1323 {
1324 size_t width = interim.GetWidth();
1325 size_t height = interim.GetHeight();
1326 Rect bounds(0,0,width,height);
1327 BitmapData data ;
1328
1329 interim.LockBits(&bounds, ImageLockModeRead,
1330 interim.GetPixelFormat(),&data);
0b7dce54 1331
0c7bd159
SC
1332 bool hasAlpha = false;
1333 for ( size_t y = 0 ; y < height && !hasAlpha ; ++y)
1334 {
1335 for( size_t x = 0 ; x < width && !hasAlpha; ++x)
1336 {
1337 ARGB *dest = (ARGB*)((BYTE*)data.Scan0 + data.Stride*y + x*4);
1338 if ( ( *dest & Color::AlphaMask ) != 0 )
1339 hasAlpha = true;
1340 }
1341 }
1342
1343 if ( hasAlpha )
1344 {
cb3a0d42 1345 image = new Bitmap(data.Width, data.Height, data.Stride,
fe31db81 1346 PixelFormat32bppARGB , (BYTE*) data.Scan0);
0c7bd159
SC
1347 }
1348 else
1349 {
1350 image = Bitmap::FromHICON(hIcon);
1351 }
1352
fe31db81
SC
1353 interim.UnlockBits(&data);
1354 }
1355
6fea499c 1356 m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ;
fe31db81 1357
6fea499c 1358 delete image ;
fe31db81
SC
1359 DeleteObject(iconInfo.hbmColor);
1360 DeleteObject(iconInfo.hbmMask);
6fea499c
SC
1361}
1362
0b7dce54
VZ
1363void wxGDIPlusContext::DoDrawFilledText(const wxString& str,
1364 wxDouble x, wxDouble y,
1365 const wxGraphicsBrush& brush)
6fea499c 1366{
bf02a7f9
SC
1367 if (m_composition == wxCOMPOSITION_DEST)
1368 return;
1369
0b7dce54
VZ
1370 wxCHECK_RET( !m_font.IsNull(),
1371 wxT("wxGDIPlusContext::DrawText - no valid font set") );
1011fbeb
SC
1372
1373 if ( str.IsEmpty())
6fea499c
SC
1374 return ;
1375
091111d6 1376 wxGDIPlusFontData * const
0b7dce54 1377 fontData = (wxGDIPlusFontData *)m_font.GetRefData();
091111d6
VZ
1378 wxGDIPlusBrushData * const
1379 brushData = (wxGDIPlusBrushData *)brush.GetRefData();
0b7dce54
VZ
1380
1381 m_context->DrawString
1382 (
1383 str.wc_str(*wxConvUI), // string to draw, always Unicode
1384 -1, // length: string is NUL-terminated
1385 fontData->GetGDIPlusFont(),
1386 PointF(x, y),
1387 StringFormat::GenericTypographic(),
1388 brushData ? brushData->GetGDIPlusBrush()
1389 : fontData->GetGDIPlusBrush()
1390 );
6fea499c
SC
1391}
1392
1393void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
1394 wxDouble *descent, wxDouble *externalLeading ) const
1395{
1011fbeb
SC
1396 wxCHECK_RET( !m_font.IsNull(), wxT("wxGDIPlusContext::GetTextExtent - no valid font set") );
1397
6fea499c
SC
1398 wxWCharBuffer s = str.wc_str( *wxConvUI );
1399 FontFamily ffamily ;
2c820406 1400 Font* f = ((wxGDIPlusFontData*)m_font.GetRefData())->GetGDIPlusFont();
cb3a0d42 1401
83576e68 1402 f->GetFamily(&ffamily) ;
6fea499c
SC
1403
1404 REAL factorY = m_context->GetDpiY() / 72.0 ;
1405
1406 REAL rDescent = ffamily.GetCellDescent(FontStyleRegular) *
83576e68 1407 f->GetSize() / ffamily.GetEmHeight(FontStyleRegular);
6fea499c 1408 REAL rAscent = ffamily.GetCellAscent(FontStyleRegular) *
83576e68 1409 f->GetSize() / ffamily.GetEmHeight(FontStyleRegular);
6fea499c 1410 REAL rHeight = ffamily.GetLineSpacing(FontStyleRegular) *
83576e68 1411 f->GetSize() / ffamily.GetEmHeight(FontStyleRegular);
6fea499c
SC
1412
1413 if ( height )
595fda6f 1414 *height = rHeight * factorY;
6fea499c 1415 if ( descent )
595fda6f 1416 *descent = rDescent * factorY;
6fea499c 1417 if ( externalLeading )
595fda6f 1418 *externalLeading = (rHeight - rAscent - rDescent) * factorY;
6fea499c 1419 // measuring empty strings is not guaranteed, so do it by hand
cb3a0d42 1420 if ( str.IsEmpty())
6fea499c
SC
1421 {
1422 if ( width )
1423 *width = 0 ;
1424 }
1425 else
1426 {
6fea499c 1427 RectF layoutRect(0,0, 100000.0f, 100000.0f);
0c7bd159 1428 StringFormat strFormat( StringFormat::GenericTypographic() );
0b7dce54 1429 strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() );
0c7bd159
SC
1430
1431 RectF bounds ;
1432 m_context->MeasureString((const wchar_t *) s , wcslen(s) , f, layoutRect, &strFormat, &bounds ) ;
6fea499c 1433 if ( width )
0c7bd159 1434 *width = bounds.Width;
6fea499c
SC
1435 }
1436}
1437
cb3a0d42 1438void wxGDIPlusContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
6fea499c
SC
1439{
1440 widths.Empty();
1441 widths.Add(0, text.length());
1442
1011fbeb
SC
1443 wxCHECK_RET( !m_font.IsNull(), wxT("wxGDIPlusContext::GetPartialTextExtents - no valid font set") );
1444
6fea499c
SC
1445 if (text.empty())
1446 return;
1447
2c820406 1448 Font* f = ((wxGDIPlusFontData*)m_font.GetRefData())->GetGDIPlusFont();
6fea499c
SC
1449 wxWCharBuffer ws = text.wc_str( *wxConvUI );
1450 size_t len = wcslen( ws ) ;
1451 wxASSERT_MSG(text.length() == len , wxT("GetPartialTextExtents not yet implemented for multichar situations"));
1452
1453 RectF layoutRect(0,0, 100000.0f, 100000.0f);
0c7bd159 1454 StringFormat strFormat( StringFormat::GenericTypographic() );
6fea499c
SC
1455
1456 CharacterRange* ranges = new CharacterRange[len] ;
1457 Region* regions = new Region[len];
0c7bd159 1458 for( size_t i = 0 ; i < len ; ++i)
6fea499c
SC
1459 {
1460 ranges[i].First = i ;
1461 ranges[i].Length = 1 ;
1462 }
1463 strFormat.SetMeasurableCharacterRanges(len,ranges);
0b7dce54 1464 strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() );
83576e68 1465 m_context->MeasureCharacterRanges(ws, -1 , f,layoutRect, &strFormat,1,regions) ;
6fea499c
SC
1466
1467 RectF bbox ;
0c7bd159 1468 for ( size_t i = 0 ; i < len ; ++i)
6fea499c
SC
1469 {
1470 regions[i].GetBounds(&bbox,m_context);
1471 widths[i] = bbox.GetRight()-bbox.GetLeft();
1472 }
1473}
1474
d9485f89 1475bool wxGDIPlusContext::ShouldOffset() const
0b7dce54 1476{
d9485f89
RD
1477 int penwidth = 0 ;
1478 if ( !m_pen.IsNull() )
1479 {
1480 penwidth = (int)((wxGDIPlusPenData*)m_pen.GetRefData())->GetWidth();
1481 if ( penwidth == 0 )
1482 penwidth = 1;
1483 }
1484 return ( penwidth % 2 ) == 1;
1485}
1486
cb3a0d42 1487void* wxGDIPlusContext::GetNativeContext()
6fea499c 1488{
cb3a0d42 1489 return m_context;
6fea499c
SC
1490}
1491
83576e68 1492// concatenates this transform with the current transform of this context
a4e73390 1493void wxGDIPlusContext::ConcatTransform( const wxGraphicsMatrix& matrix )
539e2795 1494{
a4e73390 1495 m_context->MultiplyTransform((Matrix*) matrix.GetNativeMatrix());
83576e68
SC
1496}
1497
1498// sets the transform of this context
a4e73390 1499void wxGDIPlusContext::SetTransform( const wxGraphicsMatrix& matrix )
83576e68 1500{
a4e73390 1501 m_context->SetTransform((Matrix*) matrix.GetNativeMatrix());
83576e68
SC
1502}
1503
1504// gets the matrix of this context
a4e73390 1505wxGraphicsMatrix wxGDIPlusContext::GetTransform() const
83576e68 1506{
a4e73390
SC
1507 wxGraphicsMatrix matrix = CreateMatrix();
1508 m_context->GetTransform((Matrix*) matrix.GetNativeMatrix());
1509 return matrix;
83576e68 1510}
fbd5416f
SC
1511
1512void wxGDIPlusContext::GetSize( wxDouble* width, wxDouble *height )
1513{
81e0b3d9
SC
1514 *width = m_width;
1515 *height = m_height;
fbd5416f 1516}
83576e68
SC
1517//-----------------------------------------------------------------------------
1518// wxGDIPlusRenderer declaration
1519//-----------------------------------------------------------------------------
1520
eb4083ef 1521class wxGDIPlusRenderer : public wxGraphicsRenderer
83576e68
SC
1522{
1523public :
cb3a0d42 1524 wxGDIPlusRenderer()
83576e68 1525 {
bce82a75 1526 m_loaded = -1;
cb3a0d42 1527 m_gditoken = 0;
83576e68
SC
1528 }
1529
cb3a0d42 1530 virtual ~wxGDIPlusRenderer()
83576e68 1531 {
bce82a75 1532 if ( m_loaded == 1 )
83576e68
SC
1533 {
1534 Unload();
1535 }
1536 }
1537
1538 // Context
1539
1540 virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
1541
773ccc31
SC
1542 virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc);
1543
0b822969 1544 virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc);
0b7dce54 1545
83576e68
SC
1546 virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
1547
1548 virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
1549
1550 virtual wxGraphicsContext * CreateContext( wxWindow* window );
1551
091ef146
SC
1552 virtual wxGraphicsContext * CreateMeasuringContext();
1553
83576e68
SC
1554 // Path
1555
a4e73390 1556 virtual wxGraphicsPath CreatePath();
83576e68
SC
1557
1558 // Matrix
1559
cb3a0d42 1560 virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
83576e68
SC
1561 wxDouble tx=0.0, wxDouble ty=0.0);
1562
1563
2c820406 1564 virtual wxGraphicsPen CreatePen(const wxPen& pen) ;
83576e68 1565
2c820406 1566 virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
83576e68
SC
1567
1568 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
cb3a0d42 1569 virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
83576e68
SC
1570 const wxColour&c1, const wxColour&c2) ;
1571
cb3a0d42 1572 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
83576e68 1573 // with radius r and color cColor
2c820406 1574 virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
83576e68
SC
1575 const wxColour &oColor, const wxColour &cColor) ;
1576
1577 // sets the font
2c820406 1578 virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
bce28872
SC
1579
1580 // create a native bitmap representation
1581 virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap );
0b7dce54 1582
bce28872
SC
1583 // create a subimage from a native image representation
1584 virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
1585
83576e68 1586protected :
bce82a75 1587 bool EnsureIsLoaded();
83576e68
SC
1588 void Load();
1589 void Unload();
385addaf 1590 friend class wxGDIPlusRendererModule;
83576e68
SC
1591
1592private :
bce82a75 1593 int m_loaded;
cb3a0d42 1594 ULONG_PTR m_gditoken;
83576e68
SC
1595
1596 DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusRenderer)
1597} ;
1598
1599//-----------------------------------------------------------------------------
1600// wxGDIPlusRenderer implementation
1601//-----------------------------------------------------------------------------
1602
1603IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusRenderer,wxGraphicsRenderer)
1604
1605static wxGDIPlusRenderer gs_GDIPlusRenderer;
1606
1607wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
1608{
1609 return &gs_GDIPlusRenderer;
1610}
1611
bce82a75 1612bool wxGDIPlusRenderer::EnsureIsLoaded()
83576e68 1613{
bce82a75
VS
1614 // load gdiplus.dll if not yet loaded, but don't bother doing it again
1615 // if we already tried and failed (we don't want to spend lot of time
1616 // returning NULL from wxGraphicsContext::Create(), which may be called
1617 // relatively frequently):
1618 if ( m_loaded == -1 )
83576e68
SC
1619 {
1620 Load();
1621 }
bce82a75
VS
1622
1623 return m_loaded == 1;
83576e68
SC
1624}
1625
bce82a75
VS
1626// call EnsureIsLoaded() and return returnOnFail value if it fails
1627#define ENSURE_LOADED_OR_RETURN(returnOnFail) \
1628 if ( !EnsureIsLoaded() ) \
1629 return (returnOnFail)
1630
1631
83576e68
SC
1632void wxGDIPlusRenderer::Load()
1633{
1634 GdiplusStartupInput input;
1635 GdiplusStartupOutput output;
bce82a75
VS
1636 if ( GdiplusStartup(&m_gditoken,&input,&output) == Gdiplus::Ok )
1637 {
1638 wxLogTrace("gdiplus", "successfully initialized GDI+");
1639 m_loaded = 1;
1640 }
1641 else
1642 {
1643 wxLogTrace("gdiplus", "failed to initialize GDI+, missing gdiplus.dll?");
1644 m_loaded = 0;
1645 }
83576e68
SC
1646}
1647
1648void wxGDIPlusRenderer::Unload()
1649{
1650 if ( m_gditoken )
385addaf 1651 {
83576e68 1652 GdiplusShutdown(m_gditoken);
385addaf
VZ
1653 m_gditoken = NULL;
1654 }
bce82a75 1655 m_loaded = -1; // next Load() will try again
83576e68
SC
1656}
1657
1658wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxWindowDC& dc)
1659{
bce82a75 1660 ENSURE_LOADED_OR_RETURN(NULL);
52018692 1661 wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
81e0b3d9
SC
1662 wxSize sz = dc.GetSize();
1663 return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
83576e68
SC
1664}
1665
0b822969
RR
1666wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxPrinterDC& dc)
1667{
bce82a75 1668 ENSURE_LOADED_OR_RETURN(NULL);
0b822969 1669 wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
81e0b3d9
SC
1670 wxSize sz = dc.GetSize();
1671 return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
0b822969
RR
1672}
1673
773ccc31
SC
1674wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc)
1675{
bce82a75 1676 ENSURE_LOADED_OR_RETURN(NULL);
52018692 1677 wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
81e0b3d9
SC
1678 wxSize sz = dc.GetSize();
1679 return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
773ccc31
SC
1680}
1681
091ef146
SC
1682wxGraphicsContext * wxGDIPlusRenderer::CreateMeasuringContext()
1683{
bce82a75 1684 ENSURE_LOADED_OR_RETURN(NULL);
0c7bd159 1685 return new wxGDIPlusMeasuringContext(this);
091ef146
SC
1686}
1687
83576e68
SC
1688wxGraphicsContext * wxGDIPlusRenderer::CreateContextFromNativeContext( void * context )
1689{
bce82a75 1690 ENSURE_LOADED_OR_RETURN(NULL);
83576e68
SC
1691 return new wxGDIPlusContext(this,(Graphics*) context);
1692}
1693
1694
1695wxGraphicsContext * wxGDIPlusRenderer::CreateContextFromNativeWindow( void * window )
1696{
bce82a75 1697 ENSURE_LOADED_OR_RETURN(NULL);
83576e68
SC
1698 return new wxGDIPlusContext(this,(HWND) window);
1699}
1700
1701wxGraphicsContext * wxGDIPlusRenderer::CreateContext( wxWindow* window )
1702{
bce82a75 1703 ENSURE_LOADED_OR_RETURN(NULL);
83576e68
SC
1704 return new wxGDIPlusContext(this, (HWND) window->GetHWND() );
1705}
1706
1707// Path
1708
a4e73390 1709wxGraphicsPath wxGDIPlusRenderer::CreatePath()
83576e68 1710{
bce82a75 1711 ENSURE_LOADED_OR_RETURN(wxNullGraphicsPath);
a4e73390
SC
1712 wxGraphicsPath m;
1713 m.SetRefData( new wxGDIPlusPathData(this));
1714 return m;
83576e68
SC
1715}
1716
1717
1718// Matrix
1719
cb3a0d42 1720wxGraphicsMatrix wxGDIPlusRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
83576e68
SC
1721 wxDouble tx, wxDouble ty)
1722
1723{
bce82a75 1724 ENSURE_LOADED_OR_RETURN(wxNullGraphicsMatrix);
a4e73390
SC
1725 wxGraphicsMatrix m;
1726 wxGDIPlusMatrixData* data = new wxGDIPlusMatrixData( this );
1727 data->Set( a,b,c,d,tx,ty ) ;
1728 m.SetRefData(data);
83576e68 1729 return m;
539e2795
SC
1730}
1731
cb3a0d42 1732wxGraphicsPen wxGDIPlusRenderer::CreatePen(const wxPen& pen)
6fea499c 1733{
bce82a75 1734 ENSURE_LOADED_OR_RETURN(wxNullGraphicsPen);
83576e68 1735 if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
2c820406 1736 return wxNullGraphicsPen;
83576e68 1737 else
2c820406
SC
1738 {
1739 wxGraphicsPen p;
1740 p.SetRefData(new wxGDIPlusPenData( this, pen ));
1741 return p;
1742 }
6fea499c 1743}
7ba86d93 1744
cb3a0d42 1745wxGraphicsBrush wxGDIPlusRenderer::CreateBrush(const wxBrush& brush )
539e2795 1746{
bce82a75 1747 ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
83576e68 1748 if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
2c820406 1749 return wxNullGraphicsBrush;
83576e68 1750 else
2c820406
SC
1751 {
1752 wxGraphicsBrush p;
1753 p.SetRefData(new wxGDIPlusBrushData( this, brush ));
1754 return p;
1755 }
539e2795
SC
1756}
1757
83576e68 1758// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
cb3a0d42
VZ
1759wxGraphicsBrush wxGDIPlusRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
1760 const wxColour&c1, const wxColour&c2)
539e2795 1761{
bce82a75 1762 ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
2c820406
SC
1763 wxGraphicsBrush p;
1764 wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this );
1765 d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
1766 p.SetRefData(d);
1767 return p;
1768 }
539e2795 1769
cb3a0d42 1770// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
83576e68 1771// with radius r and color cColor
2c820406 1772wxGraphicsBrush wxGDIPlusRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
cb3a0d42 1773 const wxColour &oColor, const wxColour &cColor)
83576e68 1774{
bce82a75 1775 ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
2c820406
SC
1776 wxGraphicsBrush p;
1777 wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this );
1778 d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
1779 p.SetRefData(d);
1780 return p;
83576e68 1781}
539e2795 1782
83576e68 1783// sets the font
cb3a0d42 1784wxGraphicsFont wxGDIPlusRenderer::CreateFont( const wxFont &font , const wxColour &col )
83576e68 1785{
bce82a75 1786 ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont);
83576e68 1787 if ( font.Ok() )
cb3a0d42 1788 {
2c820406
SC
1789 wxGraphicsFont p;
1790 p.SetRefData(new wxGDIPlusFontData( this , font, col ));
1791 return p;
1792 }
83576e68 1793 else
2c820406 1794 return wxNullGraphicsFont;
83576e68 1795}
7ba86d93 1796
bce28872
SC
1797wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmap( const wxBitmap &bitmap )
1798{
bce82a75 1799 ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
bce28872
SC
1800 if ( bitmap.Ok() )
1801 {
1802 wxGraphicsBitmap p;
1803 p.SetRefData(new wxGDIPlusBitmapData( this , bitmap ));
1804 return p;
1805 }
1806 else
1807 return wxNullGraphicsBitmap;
1808}
1809
1810wxGraphicsBitmap wxGDIPlusRenderer::CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1811{
bce82a75 1812 ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
bce28872
SC
1813 Bitmap* image = static_cast<wxGDIPlusBitmapData*>(bitmap.GetRefData())->GetGDIPlusBitmap();
1814 if ( image )
1815 {
1816 wxGraphicsBitmap p;
1817 p.SetRefData(new wxGDIPlusBitmapData( this , image->Clone( (REAL) x , (REAL) y , (REAL) w , (REAL) h , PixelFormat32bppPARGB) ));
1818 return p;
1819 }
1820 else
1821 return wxNullGraphicsBitmap;
1822}
1823
385addaf
VZ
1824// Shutdown GDI+ at app exit, before possible dll unload
1825class wxGDIPlusRendererModule : public wxModule
1826{
1827public:
1828 virtual bool OnInit() { return true; }
1829 virtual void OnExit() { gs_GDIPlusRenderer.Unload(); }
1830
1831private:
1832 DECLARE_DYNAMIC_CLASS(wxGDIPlusRendererModule)
1833};
1834
1835IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusRendererModule, wxModule)
1836
7ba86d93 1837#endif // wxUSE_GRAPHICS_CONTEXT