compilation fix after last commit: wxPenRefData, not wxFontRefData
[wxWidgets.git] / src / msw / pen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/pen.cpp
3 // Purpose: wxPen
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include "wx/pen.h"
20
21 #ifndef WX_PRECOMP
22 #include "wx/bitmap.h"
23 #include "wx/utils.h"
24 #endif
25
26 #include "wx/msw/private.h"
27
28 typedef WXDWORD wxMSWDash;
29
30 static int wx2msPenStyle(int wx_style);
31
32 #define M_PENDATA ((wxPenRefData*)m_refData)
33
34 class WXDLLEXPORT wxPenRefData : public wxGDIRefData
35 {
36 public:
37 wxPenRefData();
38 wxPenRefData(const wxPenRefData& data);
39 virtual ~wxPenRefData();
40
41 bool operator==(const wxPenRefData& data) const
42 {
43 // we intentionally don't compare m_hPen fields here
44 return m_style == data.m_style &&
45 m_width == data.m_width &&
46 m_join == data.m_join &&
47 m_cap == data.m_cap &&
48 m_colour == data.m_colour &&
49 (m_style != wxSTIPPLE || m_stipple.IsSameAs(data.m_stipple)) &&
50 (m_style != wxUSER_DASH ||
51 (m_nbDash == data.m_nbDash &&
52 memcmp(m_dash, data.m_dash, m_nbDash*sizeof(wxDash)) == 0));
53 }
54
55 int m_width;
56 int m_style;
57 int m_join;
58 int m_cap;
59 wxBitmap m_stipple;
60 int m_nbDash;
61 wxDash * m_dash;
62 wxColour m_colour;
63 WXHPEN m_hPen;
64
65 DECLARE_NO_ASSIGN_CLASS(wxPenRefData)
66 };
67
68 wxPenRefData::wxPenRefData()
69 {
70 m_style = wxSOLID;
71 m_width = 1;
72 m_join = wxJOIN_ROUND ;
73 m_cap = wxCAP_ROUND ;
74 m_nbDash = 0 ;
75 m_dash = (wxDash*)NULL;
76 m_hPen = 0;
77 }
78
79 wxPenRefData::wxPenRefData(const wxPenRefData& data)
80 :wxGDIRefData()
81 {
82 m_style = data.m_style;
83 m_width = data.m_width;
84 m_join = data.m_join;
85 m_cap = data.m_cap;
86 m_nbDash = data.m_nbDash;
87 m_dash = data.m_dash;
88 m_colour = data.m_colour;
89 m_hPen = 0;
90 }
91
92 wxPenRefData::~wxPenRefData()
93 {
94 if ( m_hPen )
95 ::DeleteObject((HPEN) m_hPen);
96 }
97
98 // Pens
99
100 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
101
102 wxPen::wxPen()
103 {
104 }
105
106 wxPen::~wxPen()
107 {
108 }
109
110 // Should implement Create
111 wxPen::wxPen(const wxColour& col, int Width, int Style)
112 {
113 m_refData = new wxPenRefData;
114
115 M_PENDATA->m_colour = col;
116 // M_PENDATA->m_stipple = NULL;
117 M_PENDATA->m_width = Width;
118 M_PENDATA->m_style = Style;
119 M_PENDATA->m_join = wxJOIN_ROUND ;
120 M_PENDATA->m_cap = wxCAP_ROUND ;
121 M_PENDATA->m_nbDash = 0 ;
122 M_PENDATA->m_dash = (wxDash*)NULL;
123 M_PENDATA->m_hPen = 0 ;
124
125 RealizeResource();
126 }
127
128 wxPen::wxPen(const wxBitmap& stipple, int Width)
129 {
130 m_refData = new wxPenRefData;
131
132 // M_PENDATA->m_colour = col;
133 M_PENDATA->m_stipple = stipple;
134 M_PENDATA->m_width = Width;
135 M_PENDATA->m_style = wxSTIPPLE;
136 M_PENDATA->m_join = wxJOIN_ROUND ;
137 M_PENDATA->m_cap = wxCAP_ROUND ;
138 M_PENDATA->m_nbDash = 0 ;
139 M_PENDATA->m_dash = (wxDash*)NULL;
140 M_PENDATA->m_hPen = 0 ;
141
142 RealizeResource();
143 }
144
145 bool wxPen::operator==(const wxPen& pen) const
146 {
147 const wxPenRefData *penData = wx_static_cast(const wxPenRefData*, pen.m_refData);
148
149 // an invalid pen is only equal to another invalid pen
150 return m_refData ? penData && *M_PENDATA == *penData : !penData;
151 }
152
153 bool wxPen::RealizeResource()
154 {
155 if ( !M_PENDATA || M_PENDATA->m_hPen )
156 return false;
157
158 if (M_PENDATA->m_style==wxTRANSPARENT)
159 {
160 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
161 return true;
162 }
163
164 static const int os = wxGetOsVersion();
165 COLORREF ms_colour = M_PENDATA->m_colour.GetPixel();
166
167 // Join style, Cap style, Pen Stippling
168 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
169 // Only NT can display dashed or dotted lines with width > 1
170 if ( os != wxOS_WINDOWS_NT &&
171 (M_PENDATA->m_style == wxDOT ||
172 M_PENDATA->m_style == wxLONG_DASH ||
173 M_PENDATA->m_style == wxSHORT_DASH ||
174 M_PENDATA->m_style == wxDOT_DASH ||
175 M_PENDATA->m_style == wxUSER_DASH) &&
176 M_PENDATA->m_width > 1 )
177 {
178 M_PENDATA->m_width = 1;
179 }
180
181 if (M_PENDATA->m_join==wxJOIN_ROUND &&
182 M_PENDATA->m_cap==wxCAP_ROUND &&
183 M_PENDATA->m_style!=wxUSER_DASH &&
184 M_PENDATA->m_style!=wxSTIPPLE &&
185 M_PENDATA->m_width <= 1)
186 {
187 M_PENDATA->m_hPen =
188 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
189 M_PENDATA->m_width,
190 ms_colour );
191 }
192 else
193 {
194 DWORD ms_style = PS_GEOMETRIC | wx2msPenStyle(M_PENDATA->m_style);
195
196 switch(M_PENDATA->m_join)
197 {
198 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL; break;
199 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER; break;
200 default:
201 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND; break;
202 }
203
204 switch(M_PENDATA->m_cap)
205 {
206 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE; break;
207 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT; break;
208 default:
209 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND; break;
210 }
211
212 LOGBRUSH logb;
213
214 switch(M_PENDATA->m_style)
215 {
216 case wxSTIPPLE:
217 logb.lbStyle = BS_PATTERN ;
218 if (M_PENDATA->m_stipple.Ok())
219 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP();
220 else
221 logb.lbHatch = (LONG)0;
222 break;
223 case wxBDIAGONAL_HATCH:
224 logb.lbStyle = BS_HATCHED;
225 logb.lbHatch = HS_BDIAGONAL;
226 break;
227 case wxCROSSDIAG_HATCH:
228 logb.lbStyle = BS_HATCHED;
229 logb.lbHatch = HS_DIAGCROSS;
230 break;
231 case wxFDIAGONAL_HATCH:
232 logb.lbStyle = BS_HATCHED;
233 logb.lbHatch = HS_FDIAGONAL;
234 break;
235 case wxCROSS_HATCH:
236 logb.lbStyle = BS_HATCHED;
237 logb.lbHatch = HS_CROSS;
238 break;
239 case wxHORIZONTAL_HATCH:
240 logb.lbStyle = BS_HATCHED;
241 logb.lbHatch = HS_HORIZONTAL;
242 break;
243 case wxVERTICAL_HATCH:
244 logb.lbStyle = BS_HATCHED;
245 logb.lbHatch = HS_VERTICAL;
246 break;
247 default:
248 logb.lbStyle = BS_SOLID;
249 #ifdef __WXDEBUG__
250 // this should be unnecessary (it's unused) but suppresses the Purify
251 // messages about uninitialized memory read
252 logb.lbHatch = 0;
253 #endif
254 break;
255 }
256
257 logb.lbColor = ms_colour;
258
259 wxMSWDash *real_dash;
260 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
261 {
262 real_dash = new wxMSWDash[M_PENDATA->m_nbDash];
263 int rw = M_PENDATA->m_width > 1 ? M_PENDATA->m_width : 1;
264 for ( int i = 0; i < M_PENDATA->m_nbDash; i++ )
265 real_dash[i] = M_PENDATA->m_dash[i] * rw;
266 }
267 else
268 {
269 real_dash = (wxMSWDash*)NULL;
270 }
271
272 M_PENDATA->m_hPen =
273 (WXHPEN) ExtCreatePen( ms_style,
274 M_PENDATA->m_width,
275 &logb,
276 M_PENDATA->m_style == wxUSER_DASH
277 ? M_PENDATA->m_nbDash
278 : 0,
279 (LPDWORD)real_dash );
280
281 delete [] real_dash;
282 }
283 #else // WinCE
284 M_PENDATA->m_hPen =
285 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
286 M_PENDATA->m_width,
287 ms_colour );
288 #endif // !WinCE/WinCE
289
290 return true;
291 }
292
293 WXHANDLE wxPen::GetResourceHandle() const
294 {
295 if ( !M_PENDATA )
296 return 0;
297 else
298 return (WXHANDLE)M_PENDATA->m_hPen;
299 }
300
301 bool wxPen::FreeResource(bool WXUNUSED(force))
302 {
303 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
304 {
305 DeleteObject((HPEN) M_PENDATA->m_hPen);
306 M_PENDATA->m_hPen = 0;
307 return true;
308 }
309 else return false;
310 }
311
312 bool wxPen::IsFree() const
313 {
314 return (M_PENDATA && M_PENDATA->m_hPen == 0);
315 }
316
317 wxObjectRefData* wxPen::CreateRefData() const
318 {
319 return new wxPenRefData;
320 }
321
322 wxObjectRefData* wxPen::CloneRefData(const wxObjectRefData* data) const
323 {
324 return new wxPenRefData(*wx_static_cast(const wxPenRefData*, data));
325 }
326
327 void wxPen::SetColour(const wxColour& col)
328 {
329 AllocExclusive();
330
331 M_PENDATA->m_colour = col;
332
333 RealizeResource();
334 }
335
336 void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
337 {
338 AllocExclusive();
339
340 M_PENDATA->m_colour.Set(r, g, b);
341
342 RealizeResource();
343 }
344
345 void wxPen::SetWidth(int Width)
346 {
347 AllocExclusive();
348
349 M_PENDATA->m_width = Width;
350
351 RealizeResource();
352 }
353
354 void wxPen::SetStyle(int Style)
355 {
356 AllocExclusive();
357
358 M_PENDATA->m_style = Style;
359
360 RealizeResource();
361 }
362
363 void wxPen::SetStipple(const wxBitmap& Stipple)
364 {
365 AllocExclusive();
366
367 M_PENDATA->m_stipple = Stipple;
368 M_PENDATA->m_style = wxSTIPPLE;
369
370 RealizeResource();
371 }
372
373 void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
374 {
375 AllocExclusive();
376
377 M_PENDATA->m_nbDash = nb_dashes;
378 M_PENDATA->m_dash = (wxDash *)Dash;
379
380 RealizeResource();
381 }
382
383 void wxPen::SetJoin(int Join)
384 {
385 AllocExclusive();
386
387 M_PENDATA->m_join = Join;
388
389 RealizeResource();
390 }
391
392 void wxPen::SetCap(int Cap)
393 {
394 AllocExclusive();
395
396 M_PENDATA->m_cap = Cap;
397
398 RealizeResource();
399 }
400
401 wxColour& wxPen::GetColour() const
402 {
403 return m_refData ? M_PENDATA->m_colour : wxNullColour;
404 }
405
406 int wxPen::GetWidth() const
407 {
408 return m_refData ? M_PENDATA->m_width : 0;
409 }
410
411 int wxPen::GetStyle() const
412 {
413 return m_refData ? M_PENDATA->m_style : 0;
414 }
415
416 int wxPen::GetJoin() const
417 {
418 return m_refData ? M_PENDATA->m_join : 0;
419 }
420
421 int wxPen::GetCap() const
422 {
423 return m_refData ? M_PENDATA->m_cap : 0;
424 }
425
426 int wxPen::GetDashes(wxDash** ptr) const
427 {
428 *ptr = NULL;
429 int count = 0;
430 if (m_refData)
431 {
432 *ptr = M_PENDATA->m_dash;
433 count = M_PENDATA->m_nbDash;
434 }
435 return count;
436 }
437
438 wxDash* wxPen::GetDash() const
439 {
440 wxDash* dash = NULL;
441 if (m_refData)
442 dash = M_PENDATA->m_dash;
443 return dash;
444 }
445
446 int wxPen::GetDashCount() const
447 {
448 return m_refData ? M_PENDATA->m_nbDash : 0;
449 }
450
451 wxBitmap* wxPen::GetStipple() const
452 {
453 wxBitmap* bitmap = NULL;
454 if (m_refData)
455 bitmap = &M_PENDATA->m_stipple;
456 return bitmap;
457 }
458
459 int wx2msPenStyle(int wx_style)
460 {
461 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
462 switch (wx_style)
463 {
464 case wxDOT:
465 return PS_DOT;
466
467 case wxDOT_DASH:
468 return PS_DASHDOT;
469
470 case wxSHORT_DASH:
471 case wxLONG_DASH:
472 return PS_DASH;
473
474 case wxTRANSPARENT:
475 return PS_NULL;
476
477 case wxUSER_DASH:
478 return PS_USERSTYLE;
479 }
480 #else
481 wxUnusedVar(wx_style);
482 #endif
483 return PS_SOLID;
484 }