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