]>
Commit | Line | Data |
---|---|---|
2bda0e17 | 1 | ///////////////////////////////////////////////////////////////////////////// |
46562151 | 2 | // Name: src/msw/pen.cpp |
2bda0e17 KB |
3 | // Purpose: wxPen |
4 | // Author: Julian Smart | |
5 | // Modified by: | |
6 | // Created: 04/01/98 | |
7 | // RCS-ID: $Id$ | |
6c9a19aa | 8 | // Copyright: (c) Julian Smart |
65571936 | 9 | // Licence: wxWindows licence |
2bda0e17 KB |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
2bda0e17 KB |
12 | // For compilers that support precompilation, includes "wx.h". |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
8ecff181 | 16 | #pragma hdrstop |
2bda0e17 KB |
17 | #endif |
18 | ||
f5590243 WS |
19 | #include "wx/pen.h" |
20 | ||
2bda0e17 | 21 | #ifndef WX_PRECOMP |
ce3b4b90 | 22 | #include "wx/bitmap.h" |
8ecff181 | 23 | #include "wx/utils.h" |
2bda0e17 KB |
24 | #endif |
25 | ||
26 | #include "wx/msw/private.h" | |
2bda0e17 | 27 | |
ce3b4b90 PC |
28 | typedef WXDWORD wxMSWDash; |
29 | ||
a6c81161 | 30 | static int wx2msPenStyle(int wx_style); |
ef59847c | 31 | |
ce3b4b90 PC |
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 | }; | |
2bda0e17 | 67 | |
e4a81a2e | 68 | wxPenRefData::wxPenRefData() |
2bda0e17 | 69 | { |
2bda0e17 KB |
70 | m_style = wxSOLID; |
71 | m_width = 1; | |
72 | m_join = wxJOIN_ROUND ; | |
73 | m_cap = wxCAP_ROUND ; | |
74 | m_nbDash = 0 ; | |
edd97174 | 75 | m_dash = (wxDash*)NULL; |
2bda0e17 KB |
76 | m_hPen = 0; |
77 | } | |
78 | ||
b823f5a1 | 79 | wxPenRefData::wxPenRefData(const wxPenRefData& data) |
04a18b0d | 80 | :wxGDIRefData() |
b823f5a1 JS |
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 | ||
e4a81a2e | 92 | wxPenRefData::~wxPenRefData() |
2bda0e17 | 93 | { |
8b0975a3 VZ |
94 | if ( m_hPen ) |
95 | ::DeleteObject((HPEN) m_hPen); | |
2bda0e17 KB |
96 | } |
97 | ||
98 | // Pens | |
99 | ||
ce3b4b90 PC |
100 | IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject) |
101 | ||
e4a81a2e | 102 | wxPen::wxPen() |
2bda0e17 | 103 | { |
2bda0e17 KB |
104 | } |
105 | ||
106 | wxPen::~wxPen() | |
107 | { | |
2bda0e17 KB |
108 | } |
109 | ||
110 | // Should implement Create | |
debe6624 | 111 | wxPen::wxPen(const wxColour& col, int Width, int Style) |
2bda0e17 KB |
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 ; | |
edd97174 | 122 | M_PENDATA->m_dash = (wxDash*)NULL; |
2bda0e17 KB |
123 | M_PENDATA->m_hPen = 0 ; |
124 | ||
2bda0e17 | 125 | RealizeResource(); |
2bda0e17 KB |
126 | } |
127 | ||
debe6624 | 128 | wxPen::wxPen(const wxBitmap& stipple, int Width) |
2bda0e17 | 129 | { |
c45a644e | 130 | m_refData = new wxPenRefData; |
2bda0e17 KB |
131 | |
132 | // M_PENDATA->m_colour = col; | |
c45a644e RR |
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 ; | |
edd97174 | 139 | M_PENDATA->m_dash = (wxDash*)NULL; |
c45a644e | 140 | M_PENDATA->m_hPen = 0 ; |
2bda0e17 | 141 | |
c45a644e | 142 | RealizeResource(); |
2bda0e17 KB |
143 | } |
144 | ||
ce3b4b90 PC |
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 | ||
e4a81a2e | 153 | bool wxPen::RealizeResource() |
2bda0e17 | 154 | { |
8b0975a3 VZ |
155 | if ( !M_PENDATA || M_PENDATA->m_hPen ) |
156 | return false; | |
157 | ||
158 | if (M_PENDATA->m_style==wxTRANSPARENT) | |
c45a644e | 159 | { |
8b0975a3 VZ |
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 | |
406d283a | 170 | if ( os != wxOS_WINDOWS_NT && |
f3ebca94 VZ |
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) && | |
8b0975a3 VZ |
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) | |
c45a644e | 197 | { |
8b0975a3 VZ |
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; | |
c45a644e RR |
202 | } |
203 | ||
8b0975a3 | 204 | switch(M_PENDATA->m_cap) |
c45a644e | 205 | { |
8b0975a3 VZ |
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; | |
c45a644e | 210 | } |
8b0975a3 VZ |
211 | |
212 | LOGBRUSH logb; | |
213 | ||
214 | switch(M_PENDATA->m_style) | |
c45a644e | 215 | { |
8b0975a3 VZ |
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; | |
61ba49f2 | 249 | #ifdef __WXDEBUG__ |
8b0975a3 VZ |
250 | // this should be unnecessary (it's unused) but suppresses the Purify |
251 | // messages about uninitialized memory read | |
252 | logb.lbHatch = 0; | |
61ba49f2 | 253 | #endif |
8b0975a3 | 254 | break; |
c45a644e | 255 | } |
8b0975a3 VZ |
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 | ||
286b8de5 PC |
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 ); | |
8b0975a3 VZ |
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; | |
2bda0e17 KB |
291 | } |
292 | ||
2b5f62a0 | 293 | WXHANDLE wxPen::GetResourceHandle() const |
2bda0e17 | 294 | { |
92218ce6 WS |
295 | if ( !M_PENDATA ) |
296 | return 0; | |
297 | else | |
298 | return (WXHANDLE)M_PENDATA->m_hPen; | |
2bda0e17 KB |
299 | } |
300 | ||
33ac7e6f | 301 | bool wxPen::FreeResource(bool WXUNUSED(force)) |
2bda0e17 | 302 | { |
92218ce6 WS |
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; | |
2bda0e17 KB |
310 | } |
311 | ||
e4a81a2e | 312 | bool wxPen::IsFree() const |
2bda0e17 | 313 | { |
92218ce6 | 314 | return (M_PENDATA && M_PENDATA->m_hPen == 0); |
2bda0e17 | 315 | } |
2bda0e17 | 316 | |
7c310bc8 | 317 | wxObjectRefData* wxPen::CreateRefData() const |
2bda0e17 | 318 | { |
7c310bc8 PC |
319 | return new wxFontRefData; |
320 | } | |
321 | ||
322 | wxObjectRefData* wxPen::CloneRefData(const wxObjectRefData* data) const | |
323 | { | |
324 | return new wxFontRefData(*wx_static_cast(const wxPenRefData*, data)); | |
2bda0e17 KB |
325 | } |
326 | ||
327 | void wxPen::SetColour(const wxColour& col) | |
328 | { | |
7c310bc8 | 329 | AllocExclusive(); |
2bda0e17 | 330 | |
b823f5a1 | 331 | M_PENDATA->m_colour = col; |
bbd41262 | 332 | |
2bda0e17 KB |
333 | RealizeResource(); |
334 | } | |
335 | ||
1a1498c0 | 336 | void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b) |
2bda0e17 | 337 | { |
7c310bc8 | 338 | AllocExclusive(); |
2bda0e17 | 339 | |
b823f5a1 | 340 | M_PENDATA->m_colour.Set(r, g, b); |
bbd41262 | 341 | |
2bda0e17 KB |
342 | RealizeResource(); |
343 | } | |
344 | ||
debe6624 | 345 | void wxPen::SetWidth(int Width) |
2bda0e17 | 346 | { |
7c310bc8 | 347 | AllocExclusive(); |
2bda0e17 | 348 | |
b823f5a1 | 349 | M_PENDATA->m_width = Width; |
2bda0e17 | 350 | |
2bda0e17 KB |
351 | RealizeResource(); |
352 | } | |
353 | ||
debe6624 | 354 | void wxPen::SetStyle(int Style) |
2bda0e17 | 355 | { |
7c310bc8 | 356 | AllocExclusive(); |
2bda0e17 | 357 | |
b823f5a1 | 358 | M_PENDATA->m_style = Style; |
2bda0e17 | 359 | |
2bda0e17 KB |
360 | RealizeResource(); |
361 | } | |
362 | ||
363 | void wxPen::SetStipple(const wxBitmap& Stipple) | |
364 | { | |
7c310bc8 | 365 | AllocExclusive(); |
2bda0e17 | 366 | |
b823f5a1 JS |
367 | M_PENDATA->m_stipple = Stipple; |
368 | M_PENDATA->m_style = wxSTIPPLE; | |
bbd41262 | 369 | |
2bda0e17 KB |
370 | RealizeResource(); |
371 | } | |
372 | ||
debe6624 | 373 | void wxPen::SetDashes(int nb_dashes, const wxDash *Dash) |
2bda0e17 | 374 | { |
7c310bc8 | 375 | AllocExclusive(); |
2bda0e17 | 376 | |
b823f5a1 | 377 | M_PENDATA->m_nbDash = nb_dashes; |
edd97174 | 378 | M_PENDATA->m_dash = (wxDash *)Dash; |
bbd41262 | 379 | |
2bda0e17 KB |
380 | RealizeResource(); |
381 | } | |
382 | ||
debe6624 | 383 | void wxPen::SetJoin(int Join) |
2bda0e17 | 384 | { |
7c310bc8 | 385 | AllocExclusive(); |
2bda0e17 | 386 | |
b823f5a1 | 387 | M_PENDATA->m_join = Join; |
2bda0e17 | 388 | |
2bda0e17 KB |
389 | RealizeResource(); |
390 | } | |
391 | ||
debe6624 | 392 | void wxPen::SetCap(int Cap) |
2bda0e17 | 393 | { |
7c310bc8 | 394 | AllocExclusive(); |
2bda0e17 | 395 | |
b823f5a1 | 396 | M_PENDATA->m_cap = Cap; |
2bda0e17 | 397 | |
2bda0e17 KB |
398 | RealizeResource(); |
399 | } | |
400 | ||
ce3b4b90 PC |
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 | ||
2bda0e17 KB |
459 | int wx2msPenStyle(int wx_style) |
460 | { | |
07505825 | 461 | #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) |
c45a644e | 462 | switch (wx_style) |
bbd41262 | 463 | { |
07505825 WS |
464 | case wxDOT: |
465 | return PS_DOT; | |
c45a644e | 466 | |
07505825 WS |
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: | |
286b8de5 | 478 | return PS_USERSTYLE; |
07505825 | 479 | } |
2bda0e17 | 480 | #else |
07505825 | 481 | wxUnusedVar(wx_style); |
2bda0e17 | 482 | #endif |
07505825 | 483 | return PS_SOLID; |
2bda0e17 | 484 | } |