]> git.saurik.com Git - wxWidgets.git/blame - src/msw/pen.cpp
svn not cvs
[wxWidgets.git] / src / msw / pen.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
46562151 2// Name: src/msw/pen.cpp
2bda0e17
KB
3// Purpose: wxPen
4// Author: Julian Smart
8c583381 5// Modified by: Vadim Zeitlin: refactored wxPen code to wxPenRefData
2bda0e17
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
8c583381
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
8ecff181 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
f5590243
WS
27#include "wx/pen.h"
28
2bda0e17 29#ifndef WX_PRECOMP
ce3b4b90 30 #include "wx/bitmap.h"
8ecff181 31 #include "wx/utils.h"
2bda0e17
KB
32#endif
33
34#include "wx/msw/private.h"
2bda0e17 35
8c583381 36#define M_PENDATA ((wxPenRefData*)m_refData)
ce3b4b90 37
8c583381
VZ
38// Win32 has ExtCreatePen() but WinCE doesn't
39#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
40 #define wxHAVE_EXT_CREATE_PEN
41#endif
ef59847c 42
8c583381
VZ
43// ----------------------------------------------------------------------------
44// wxPenRefData: contains information about an HPEN and its handle
45// ----------------------------------------------------------------------------
ce3b4b90
PC
46
47class WXDLLEXPORT wxPenRefData : public wxGDIRefData
48{
49public:
8c583381
VZ
50 // ctors and dtor
51 // --------------
52
ce3b4b90
PC
53 wxPenRefData();
54 wxPenRefData(const wxPenRefData& data);
8c583381
VZ
55 wxPenRefData(const wxColour& col, int width, int style);
56 wxPenRefData(const wxBitmap& stipple, int width);
ce3b4b90
PC
57 virtual ~wxPenRefData();
58
59 bool operator==(const wxPenRefData& data) const
60 {
61 // we intentionally don't compare m_hPen fields here
62 return m_style == data.m_style &&
63 m_width == data.m_width &&
64 m_join == data.m_join &&
65 m_cap == data.m_cap &&
66 m_colour == data.m_colour &&
67 (m_style != wxSTIPPLE || m_stipple.IsSameAs(data.m_stipple)) &&
68 (m_style != wxUSER_DASH ||
69 (m_nbDash == data.m_nbDash &&
70 memcmp(m_dash, data.m_dash, m_nbDash*sizeof(wxDash)) == 0));
71 }
72
8c583381
VZ
73
74 // accessors and setters
75 // ---------------------
76
77 wxColour& GetColour() const { return wx_const_cast(wxColour&, m_colour); }
78 int GetWidth() const { return m_width; }
79 int GetStyle() const { return m_style; }
80 int GetJoin() const { return m_join; }
81 int GetCap() const { return m_cap; }
82 wxDash* GetDash() const { return m_dash; }
83 int GetDashCount() const { return m_nbDash; }
84 wxBitmap* GetStipple() const { return wx_const_cast(wxBitmap *, &m_stipple); }
85
86 void SetColour(const wxColour& col) { Free(); m_colour = col; }
87 void SetWidth(int width) { Free(); m_width = width; }
88 void SetStyle(int style) { Free(); m_style = style; }
89 void SetStipple(const wxBitmap& stipple)
90 {
91 Free();
92
93 m_style = wxSTIPPLE;
94 m_stipple = stipple;
95 }
96
97 void SetDashes(int nb_dashes, const wxDash *dash)
98 {
99 Free();
100
101 m_nbDash = nb_dashes;
102 m_dash = wx_const_cast(wxDash *, dash);
103 }
104
105 void SetJoin(int join) { Free(); m_join = join; }
106 void SetCap(int cap) { Free(); m_cap = cap; }
107
108
109 // HPEN management
110 // ---------------
111
112 // create the HPEN if we don't have it yet
113 bool Alloc();
114
115 // get the HPEN creating it on demand
116 WXHPEN GetHPEN() const;
117
118 // return true if we have a valid HPEN
119 bool HasHPEN() const { return m_hPen != 0; }
120
121 // return true if we had a valid handle before, false otherwise
122 bool Free();
123
124private:
125 // initialize the fields which have reasonable default values
126 //
127 // doesn't initialize m_width and m_style which must be initialize in ctor
128 void Init()
129 {
130 m_join = wxJOIN_ROUND;
131 m_cap = wxCAP_ROUND;
132 m_nbDash = 0;
133 m_dash = NULL;
134 m_hPen = 0;
135 }
136
ce3b4b90
PC
137 int m_width;
138 int m_style;
139 int m_join;
140 int m_cap;
141 wxBitmap m_stipple;
142 int m_nbDash;
143 wxDash * m_dash;
144 wxColour m_colour;
8c583381 145 HPEN m_hPen;
ce3b4b90
PC
146
147 DECLARE_NO_ASSIGN_CLASS(wxPenRefData)
148};
2bda0e17 149
8c583381
VZ
150// ============================================================================
151// implementation
152// ============================================================================
153
154// ----------------------------------------------------------------------------
155// wxPenRefData ctors/dtor
156// ----------------------------------------------------------------------------
157
e4a81a2e 158wxPenRefData::wxPenRefData()
2bda0e17 159{
8c583381
VZ
160 Init();
161
162 m_style = wxSOLID;
163 m_width = 1;
2bda0e17
KB
164}
165
b823f5a1 166wxPenRefData::wxPenRefData(const wxPenRefData& data)
04a18b0d 167 :wxGDIRefData()
b823f5a1
JS
168{
169 m_style = data.m_style;
170 m_width = data.m_width;
171 m_join = data.m_join;
172 m_cap = data.m_cap;
173 m_nbDash = data.m_nbDash;
174 m_dash = data.m_dash;
175 m_colour = data.m_colour;
176 m_hPen = 0;
177}
178
8c583381 179wxPenRefData::wxPenRefData(const wxColour& col, int width, int style)
2bda0e17 180{
8c583381 181 Init();
2bda0e17 182
8c583381
VZ
183 m_style = style;
184 m_width = width;
2bda0e17 185
8c583381
VZ
186 m_colour = col;
187}
ce3b4b90 188
8c583381 189wxPenRefData::wxPenRefData(const wxBitmap& stipple, int width)
2bda0e17 190{
8c583381
VZ
191 Init();
192
193 m_style = wxSTIPPLE;
194 m_width = width;
195
196 m_stipple = stipple;
2bda0e17
KB
197}
198
8c583381 199wxPenRefData::~wxPenRefData()
2bda0e17 200{
8c583381
VZ
201 if ( m_hPen )
202 ::DeleteObject(m_hPen);
2bda0e17
KB
203}
204
8c583381
VZ
205// ----------------------------------------------------------------------------
206// wxPenRefData HPEN management
207// ----------------------------------------------------------------------------
208
209#ifdef wxHAVE_EXT_CREATE_PEN
210
211static int ConvertPenStyle(int style)
2bda0e17 212{
8c583381
VZ
213 switch ( style )
214 {
215 case wxDOT:
216 return PS_DOT;
217
218 case wxDOT_DASH:
219 return PS_DASHDOT;
220
221 case wxSHORT_DASH:
222 case wxLONG_DASH:
223 return PS_DASH;
224
225 case wxTRANSPARENT:
226 return PS_NULL;
2bda0e17 227
8c583381
VZ
228 case wxUSER_DASH:
229 return PS_USERSTYLE;
2bda0e17 230
8c583381
VZ
231 default:
232 wxFAIL_MSG( _T("unknown pen style") );
233 // fall through
234
235 case wxSTIPPLE:
236 case wxBDIAGONAL_HATCH:
237 case wxCROSSDIAG_HATCH:
238 case wxFDIAGONAL_HATCH:
239 case wxCROSS_HATCH:
240 case wxHORIZONTAL_HATCH:
241 case wxVERTICAL_HATCH:
242 case wxSOLID:
243 return PS_SOLID;
244 }
2bda0e17
KB
245}
246
8c583381 247static int ConvertJoinStyle(int join)
2bda0e17 248{
8c583381
VZ
249 switch( join )
250 {
251 case wxJOIN_BEVEL:
252 return PS_JOIN_BEVEL;
2bda0e17 253
8c583381
VZ
254 case wxJOIN_MITER:
255 return PS_JOIN_MITER;
2bda0e17 256
8c583381
VZ
257 default:
258 wxFAIL_MSG( _T("unknown pen join style") );
259 // fall through
260
261 case wxJOIN_ROUND:
262 return PS_JOIN_ROUND;
263 }
2bda0e17
KB
264}
265
8c583381 266static int ConvertCapStyle(int cap)
ce3b4b90 267{
8c583381
VZ
268 switch ( cap )
269 {
270 case wxCAP_PROJECTING:
271 return PS_ENDCAP_SQUARE;
ce3b4b90 272
8c583381
VZ
273 case wxCAP_BUTT:
274 return PS_ENDCAP_FLAT;
275
276 default:
277 wxFAIL_MSG( _T("unknown pen cap style") );
278 // fall through
279
280 case wxCAP_ROUND:
281 return PS_ENDCAP_ROUND;
282 }
ce3b4b90
PC
283}
284
8c583381
VZ
285#endif // wxHAVE_EXT_CREATE_PEN
286
287bool wxPenRefData::Alloc()
2bda0e17 288{
8c583381 289 if ( m_hPen )
8b0975a3
VZ
290 return false;
291
8c583381 292 if ( m_style == wxTRANSPARENT )
c45a644e 293 {
8c583381 294 m_hPen = (HPEN)::GetStockObject(NULL_PEN);
8b0975a3
VZ
295 return true;
296 }
297
8c583381 298 const COLORREF col = m_colour.GetPixel();
8b0975a3 299
8c583381 300#ifdef wxHAVE_EXT_CREATE_PEN
8b0975a3 301 // Only NT can display dashed or dotted lines with width > 1
8c583381 302 static const int os = wxGetOsVersion();
406d283a 303 if ( os != wxOS_WINDOWS_NT &&
8c583381
VZ
304 (m_style == wxDOT ||
305 m_style == wxLONG_DASH ||
306 m_style == wxSHORT_DASH ||
307 m_style == wxDOT_DASH ||
308 m_style == wxUSER_DASH) &&
309 m_width > 1 )
8b0975a3 310 {
8c583381 311 m_width = 1;
8b0975a3
VZ
312 }
313
8c583381
VZ
314 // check if it's a standard kind of pen which can be created with just
315 // CreatePen()
316 if ( m_join == wxJOIN_ROUND &&
317 m_cap == wxCAP_ROUND &&
318 m_style != wxUSER_DASH &&
319 m_style != wxSTIPPLE &&
320 (m_width <= 1 || m_style == wxSOLID) )
321#endif // !wxHAVE_EXT_CREATE_PEN
8b0975a3 322 {
8c583381 323 m_hPen = ::CreatePen(ConvertPenStyle(m_style), m_width, col);
8b0975a3 324 }
8c583381
VZ
325#ifdef wxHAVE_EXT_CREATE_PEN
326 else // need to use ExtCreatePen()
8b0975a3 327 {
8c583381
VZ
328 DWORD styleMSW = PS_GEOMETRIC |
329 ConvertPenStyle(m_style) |
330 ConvertJoinStyle(m_join) |
331 ConvertCapStyle(m_cap);
8b0975a3 332
8c583381
VZ
333 LOGBRUSH lb;
334 switch( m_style )
c45a644e 335 {
8b0975a3 336 case wxSTIPPLE:
8c583381
VZ
337 lb.lbStyle = BS_PATTERN;
338 lb.lbHatch = (LONG)m_stipple.GetHBITMAP();
8b0975a3 339 break;
8c583381 340
8b0975a3 341 case wxBDIAGONAL_HATCH:
8c583381
VZ
342 lb.lbStyle = BS_HATCHED;
343 lb.lbHatch = HS_BDIAGONAL;
8b0975a3 344 break;
8c583381 345
8b0975a3 346 case wxCROSSDIAG_HATCH:
8c583381
VZ
347 lb.lbStyle = BS_HATCHED;
348 lb.lbHatch = HS_DIAGCROSS;
8b0975a3 349 break;
8c583381 350
8b0975a3 351 case wxFDIAGONAL_HATCH:
8c583381
VZ
352 lb.lbStyle = BS_HATCHED;
353 lb.lbHatch = HS_FDIAGONAL;
8b0975a3 354 break;
8c583381 355
8b0975a3 356 case wxCROSS_HATCH:
8c583381
VZ
357 lb.lbStyle = BS_HATCHED;
358 lb.lbHatch = HS_CROSS;
8b0975a3 359 break;
8c583381 360
8b0975a3 361 case wxHORIZONTAL_HATCH:
8c583381
VZ
362 lb.lbStyle = BS_HATCHED;
363 lb.lbHatch = HS_HORIZONTAL;
8b0975a3 364 break;
8c583381 365
8b0975a3 366 case wxVERTICAL_HATCH:
8c583381
VZ
367 lb.lbStyle = BS_HATCHED;
368 lb.lbHatch = HS_VERTICAL;
8b0975a3 369 break;
8c583381 370
8b0975a3 371 default:
8c583381 372 lb.lbStyle = BS_SOLID;
61ba49f2 373#ifdef __WXDEBUG__
8c583381
VZ
374 // this should be unnecessary (it's unused) but suppresses the
375 // Purify messages about uninitialized memory read
376 lb.lbHatch = 0;
61ba49f2 377#endif
8b0975a3 378 break;
c45a644e 379 }
8b0975a3 380
8c583381 381 lb.lbColor = col;
8b0975a3 382
8c583381
VZ
383 DWORD *dash;
384 if ( m_style == wxUSER_DASH && m_nbDash && m_dash )
8b0975a3 385 {
8c583381
VZ
386 dash = new DWORD[m_nbDash];
387 int rw = m_width > 1 ? m_width : 1;
388 for ( int i = 0; i < m_nbDash; i++ )
389 dash[i] = m_dash[i] * rw;
8b0975a3
VZ
390 }
391 else
392 {
8c583381 393 dash = NULL;
8b0975a3
VZ
394 }
395
8c583381 396 m_hPen = ::ExtCreatePen(styleMSW, m_width, &lb, m_nbDash, (LPDWORD)dash);
8b0975a3 397
8c583381 398 delete [] dash;
8b0975a3 399 }
8c583381
VZ
400#endif // wxHAVE_EXT_CREATE_PEN
401
402 return m_hPen != 0;
403}
404
405bool wxPenRefData::Free()
406{
407 if ( !m_hPen )
408 return false;
409
410 ::DeleteObject(m_hPen);
411 m_hPen = 0;
412
413 return true;
414}
415
416WXHPEN wxPenRefData::GetHPEN() const
417{
418 if ( !m_hPen )
419 wx_const_cast(wxPenRefData *, this)->Alloc();
420
421 return (WXHPEN)m_hPen;
422}
423
424// ----------------------------------------------------------------------------
425// wxPen
426// ----------------------------------------------------------------------------
427
428IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
429
430wxPen::wxPen(const wxColour& col, int width, int style)
431{
432 m_refData = new wxPenRefData(col, width, style);
433}
434
435wxPen::wxPen(const wxBitmap& stipple, int width)
436{
437 m_refData = new wxPenRefData(stipple, width);
438}
439
440bool wxPen::operator==(const wxPen& pen) const
441{
442 const wxPenRefData *
443 penData = wx_static_cast(const wxPenRefData *, pen.m_refData);
444
445 // an invalid pen is only equal to another invalid pen
446 return m_refData ? penData && *M_PENDATA == *penData : !penData;
447}
8b0975a3 448
8c583381
VZ
449bool wxPen::RealizeResource()
450{
451 return M_PENDATA && M_PENDATA->Alloc();
2bda0e17
KB
452}
453
2b5f62a0 454WXHANDLE wxPen::GetResourceHandle() const
2bda0e17 455{
8c583381 456 return M_PENDATA ? M_PENDATA->GetHPEN() : 0;
2bda0e17
KB
457}
458
33ac7e6f 459bool wxPen::FreeResource(bool WXUNUSED(force))
2bda0e17 460{
8c583381 461 return M_PENDATA && M_PENDATA->Free();
2bda0e17
KB
462}
463
e4a81a2e 464bool wxPen::IsFree() const
2bda0e17 465{
8c583381 466 return M_PENDATA && !M_PENDATA->HasHPEN();
2bda0e17 467}
2bda0e17 468
7c310bc8 469wxObjectRefData* wxPen::CreateRefData() const
2bda0e17 470{
385fa875 471 return new wxPenRefData;
7c310bc8
PC
472}
473
474wxObjectRefData* wxPen::CloneRefData(const wxObjectRefData* data) const
475{
385fa875 476 return new wxPenRefData(*wx_static_cast(const wxPenRefData*, data));
2bda0e17
KB
477}
478
479void wxPen::SetColour(const wxColour& col)
480{
7c310bc8 481 AllocExclusive();
2bda0e17 482
8c583381 483 M_PENDATA->SetColour(col);
2bda0e17
KB
484}
485
1a1498c0 486void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
2bda0e17 487{
8c583381 488 SetColour(wxColour(r, g, b));
2bda0e17
KB
489}
490
8c583381 491void wxPen::SetWidth(int width)
2bda0e17 492{
7c310bc8 493 AllocExclusive();
2bda0e17 494
8c583381 495 M_PENDATA->SetWidth(width);
2bda0e17
KB
496}
497
8c583381 498void wxPen::SetStyle(int style)
2bda0e17 499{
7c310bc8 500 AllocExclusive();
2bda0e17 501
8c583381 502 M_PENDATA->SetStyle(style);
2bda0e17
KB
503}
504
8c583381 505void wxPen::SetStipple(const wxBitmap& stipple)
2bda0e17 506{
7c310bc8 507 AllocExclusive();
2bda0e17 508
8c583381 509 M_PENDATA->SetStipple(stipple);
2bda0e17
KB
510}
511
8c583381 512void wxPen::SetDashes(int nb_dashes, const wxDash *dash)
2bda0e17 513{
7c310bc8 514 AllocExclusive();
2bda0e17 515
8c583381 516 M_PENDATA->SetDashes(nb_dashes, dash);
2bda0e17
KB
517}
518
8c583381 519void wxPen::SetJoin(int join)
2bda0e17 520{
7c310bc8 521 AllocExclusive();
2bda0e17 522
8c583381 523 M_PENDATA->SetJoin(join);
2bda0e17
KB
524}
525
8c583381 526void wxPen::SetCap(int cap)
2bda0e17 527{
7c310bc8 528 AllocExclusive();
2bda0e17 529
8c583381 530 M_PENDATA->SetCap(cap);
2bda0e17
KB
531}
532
ce3b4b90
PC
533wxColour& wxPen::GetColour() const
534{
8c583381 535 return m_refData ? M_PENDATA->GetColour() : wxNullColour;
ce3b4b90
PC
536}
537
538int wxPen::GetWidth() const
539{
8c583381 540 return m_refData ? M_PENDATA->GetWidth() : 0;
ce3b4b90
PC
541}
542
543int wxPen::GetStyle() const
544{
8c583381 545 return m_refData ? M_PENDATA->GetStyle() : 0;
ce3b4b90
PC
546}
547
548int wxPen::GetJoin() const
549{
8c583381 550 return m_refData ? M_PENDATA->GetJoin() : 0;
ce3b4b90
PC
551}
552
553int wxPen::GetCap() const
554{
8c583381 555 return m_refData ? M_PENDATA->GetCap() : 0;
ce3b4b90
PC
556}
557
558int wxPen::GetDashes(wxDash** ptr) const
559{
8c583381 560 if ( !m_refData )
ce3b4b90 561 {
8c583381
VZ
562 *ptr = NULL;
563 return 0;
ce3b4b90 564 }
8c583381
VZ
565
566 *ptr = M_PENDATA->GetDash();
567 return M_PENDATA->GetDashCount();
ce3b4b90
PC
568}
569
570wxDash* wxPen::GetDash() const
571{
8c583381 572 return m_refData ? M_PENDATA->GetDash() : NULL;
ce3b4b90
PC
573}
574
575int wxPen::GetDashCount() const
576{
8c583381 577 return m_refData ? M_PENDATA->GetDashCount() : 0;
ce3b4b90
PC
578}
579
580wxBitmap* wxPen::GetStipple() const
581{
8c583381 582 return m_refData ? M_PENDATA->GetStipple() : NULL;
2bda0e17 583}