]> git.saurik.com Git - wxWidgets.git/blame - src/msw/pen.cpp
wxWindow::Fit() infinite loop bug fixed
[wxWidgets.git] / src / msw / pen.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: 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 and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "pen.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <stdio.h>
25#include "wx/setup.h"
26#include "wx/list.h"
27#include "wx/utils.h"
28#include "wx/app.h"
29#include "wx/pen.h"
30#endif
31
32#include "wx/msw/private.h"
33#include "assert.h"
34
35#if !USE_SHARED_LIBRARIES
36IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
37#endif
38
e4a81a2e 39wxPenRefData::wxPenRefData()
2bda0e17 40{
2bda0e17
KB
41 m_style = wxSOLID;
42 m_width = 1;
43 m_join = wxJOIN_ROUND ;
44 m_cap = wxCAP_ROUND ;
45 m_nbDash = 0 ;
46 m_dash = 0 ;
47 m_hPen = 0;
48}
49
b823f5a1
JS
50wxPenRefData::wxPenRefData(const wxPenRefData& data)
51{
52 m_style = data.m_style;
53 m_width = data.m_width;
54 m_join = data.m_join;
55 m_cap = data.m_cap;
56 m_nbDash = data.m_nbDash;
57 m_dash = data.m_dash;
58 m_colour = data.m_colour;
59 m_hPen = 0;
60}
61
e4a81a2e 62wxPenRefData::~wxPenRefData()
2bda0e17
KB
63{
64 if ( m_hPen )
65 ::DeleteObject((HPEN) m_hPen);
66}
67
68// Pens
69
e4a81a2e 70wxPen::wxPen()
2bda0e17
KB
71{
72 if ( wxThePenList )
73 wxThePenList->AddPen(this);
74}
75
76wxPen::~wxPen()
77{
78 if (wxThePenList)
79 wxThePenList->RemovePen(this);
80}
81
82// Should implement Create
debe6624 83wxPen::wxPen(const wxColour& col, int Width, int Style)
2bda0e17
KB
84{
85 m_refData = new wxPenRefData;
86
87 M_PENDATA->m_colour = col;
88// M_PENDATA->m_stipple = NULL;
89 M_PENDATA->m_width = Width;
90 M_PENDATA->m_style = Style;
91 M_PENDATA->m_join = wxJOIN_ROUND ;
92 M_PENDATA->m_cap = wxCAP_ROUND ;
93 M_PENDATA->m_nbDash = 0 ;
94 M_PENDATA->m_dash = 0 ;
95 M_PENDATA->m_hPen = 0 ;
96
97#ifndef __WIN32__
98 // In Windows, only a pen of width = 1 can be dotted or dashed!
99 if ((Style == wxDOT) || (Style == wxLONG_DASH) ||
100 (Style == wxSHORT_DASH) || (Style == wxDOT_DASH) ||
101 (Style == wxUSER_DASH))
102 M_PENDATA->m_width = 1;
103#else
104/***
105 DWORD vers = GetVersion() ;
106 WORD high = HIWORD(vers) ; // high bit=0 for NT, 1 for Win32s
107 // Win32s doesn't support wide dashed pens
108
109 if ((high&0x8000)!=0)
110***/
111 if (wxGetOsVersion()==wxWIN32S)
112 {
113 // In Windows, only a pen of width = 1 can be dotted or dashed!
114 if ((Style == wxDOT) || (Style == wxLONG_DASH) ||
115 (Style == wxSHORT_DASH) || (Style == wxDOT_DASH) ||
116 (Style == wxUSER_DASH))
117 M_PENDATA->m_width = 1;
118 }
119#endif
120 RealizeResource();
121
122 if ( wxThePenList )
123 wxThePenList->AddPen(this);
124}
125
debe6624 126wxPen::wxPen(const wxBitmap& stipple, int Width)
2bda0e17
KB
127{
128 m_refData = new wxPenRefData;
129
130// M_PENDATA->m_colour = col;
131 M_PENDATA->m_stipple = stipple;
132 M_PENDATA->m_width = Width;
133 M_PENDATA->m_style = wxSTIPPLE;
134 M_PENDATA->m_join = wxJOIN_ROUND ;
135 M_PENDATA->m_cap = wxCAP_ROUND ;
136 M_PENDATA->m_nbDash = 0 ;
137 M_PENDATA->m_dash = 0 ;
138 M_PENDATA->m_hPen = 0 ;
139
140 RealizeResource();
141
142 if ( wxThePenList )
143 wxThePenList->AddPen(this);
144}
145
e4a81a2e 146bool wxPen::RealizeResource()
2bda0e17
KB
147{
148 if (M_PENDATA && (M_PENDATA->m_hPen == 0))
149 {
150 if (M_PENDATA->m_style==wxTRANSPARENT)
151 {
152 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
153 return TRUE;
154 }
155
156 COLORREF ms_colour = 0 ;
157 ms_colour = M_PENDATA->m_colour.GetPixel() ;
158
159 // Join style, Cap style, Pen Stippling only on Win32.
160 // Currently no time to find equivalent on Win3.1, sorry
161 // [if such equiv exist!!]
162#ifdef __WIN32__
163 if (M_PENDATA->m_join==wxJOIN_ROUND &&
164 M_PENDATA->m_cap==wxCAP_ROUND &&
165 M_PENDATA->m_style!=wxUSER_DASH &&
6f65e337
JS
166 M_PENDATA->m_style!=wxSTIPPLE &&
167 M_PENDATA->m_width <= 1
2bda0e17
KB
168 )
169 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
170 else
171 {
172 DWORD ms_style = PS_GEOMETRIC|wx2msPenStyle(M_PENDATA->m_style) ;
173
174 LOGBRUSH logb ;
175
176 switch(M_PENDATA->m_join)
177 {
178 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL ; break ;
179 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER ; break ;
180 default:
181 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND ; break ;
182 }
183
184 switch(M_PENDATA->m_cap)
185 {
186 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE ; break ;
187 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT ; break ;
188 default:
189 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND ; break ;
190 }
191
192 switch(M_PENDATA->m_style)
193 {
194 case wxSTIPPLE:
195 logb.lbStyle = BS_PATTERN ;
196 if (M_PENDATA->m_stipple.Ok())
197 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP() ;
198 else
199 logb.lbHatch = (LONG)0 ;
200 break ;
201 case wxBDIAGONAL_HATCH:
202 logb.lbStyle = BS_HATCHED ;
203 logb.lbHatch = HS_BDIAGONAL ;
204 break ;
205 case wxCROSSDIAG_HATCH:
206 logb.lbStyle = BS_HATCHED ;
207 logb.lbHatch = HS_DIAGCROSS ;
208 break ;
209 case wxFDIAGONAL_HATCH:
210 logb.lbStyle = BS_HATCHED ;
211 logb.lbHatch = HS_FDIAGONAL ;
212 break ;
213 case wxCROSS_HATCH:
214 logb.lbStyle = BS_HATCHED ;
215 logb.lbHatch = HS_CROSS ;
216 break ;
217 case wxHORIZONTAL_HATCH:
218 logb.lbStyle = BS_HATCHED ;
219 logb.lbHatch = HS_HORIZONTAL ;
220 break ;
221 case wxVERTICAL_HATCH:
222 logb.lbStyle = BS_HATCHED ;
223 logb.lbHatch = HS_VERTICAL ;
224 break ;
225 default:
226 logb.lbStyle = BS_SOLID ;
61ba49f2
VZ
227 // this should be unnecessary (it's unused) but suppresses the Purigy
228 // messages about uninitialized memory read
229#ifdef __WXDEBUG__
230 logb.lbHatch = 0;
231#endif
2bda0e17
KB
232 break ;
233 }
234 logb.lbColor = ms_colour ;
235 wxDash *real_dash ;
236 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
237 {
238 real_dash = new wxDash[M_PENDATA->m_nbDash] ;
239 int i;
240 for (i=0;i<M_PENDATA->m_nbDash;i++)
241 real_dash[i] = M_PENDATA->m_dash[i] * M_PENDATA->m_width ;
242 }
243 else
244 real_dash = 0 ;
245
246 // Win32s doesn't have ExtCreatePen function...
247 if (wxGetOsVersion()==wxWINDOWS_NT || wxGetOsVersion()==wxWIN95)
248 M_PENDATA->m_hPen = (WXHPEN) ExtCreatePen(ms_style,M_PENDATA->m_width,&logb,
249 M_PENDATA->m_style==wxUSER_DASH ? M_PENDATA->m_nbDash:0, (const DWORD *)real_dash);
250 else
251 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
252
253 if (real_dash)
254 delete [] real_dash ;
255 }
256#else
257 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
258#endif
b2aef89b 259#ifdef WXDEBUG_CREATE
2bda0e17
KB
260 if (M_PENDATA->m_hPen==0)
261 wxError("Cannot create pen","Internal error") ;
262#endif
263 return TRUE;
264 }
265 return FALSE;
266}
267
e4a81a2e 268WXHANDLE wxPen::GetResourceHandle()
2bda0e17
KB
269{
270 if ( !M_PENDATA )
271 return 0;
272 else
273 return (WXHANDLE)M_PENDATA->m_hPen;
274}
275
276bool wxPen::FreeResource(bool force)
277{
278 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
279 {
280 DeleteObject((HPEN) M_PENDATA->m_hPen);
281 M_PENDATA->m_hPen = 0;
282 return TRUE;
283 }
284 else return FALSE;
285}
286
e4a81a2e 287bool wxPen::IsFree() const
2bda0e17 288{
b823f5a1 289 return (M_PENDATA && M_PENDATA->m_hPen == 0);
2bda0e17 290}
2bda0e17 291
b823f5a1 292void wxPen::Unshare()
2bda0e17 293{
b823f5a1
JS
294 // Don't change shared data
295 if (!m_refData)
296 {
297 m_refData = new wxPenRefData();
298 }
299 else
300 {
301 wxPenRefData* ref = new wxPenRefData(*(wxPenRefData*)m_refData);
302 UnRef();
303 m_refData = ref;
304 }
2bda0e17
KB
305}
306
307void wxPen::SetColour(const wxColour& col)
308{
b823f5a1 309 Unshare();
2bda0e17 310
b823f5a1 311 M_PENDATA->m_colour = col;
2bda0e17 312
2bda0e17
KB
313 RealizeResource();
314}
315
e4a81a2e 316void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
2bda0e17 317{
b823f5a1 318 Unshare();
2bda0e17 319
b823f5a1 320 M_PENDATA->m_colour.Set(r, g, b);
2bda0e17 321
2bda0e17
KB
322 RealizeResource();
323}
324
debe6624 325void wxPen::SetWidth(int Width)
2bda0e17 326{
b823f5a1 327 Unshare();
2bda0e17 328
b823f5a1 329 M_PENDATA->m_width = Width;
2bda0e17 330
2bda0e17
KB
331 RealizeResource();
332}
333
debe6624 334void wxPen::SetStyle(int Style)
2bda0e17 335{
b823f5a1 336 Unshare();
2bda0e17 337
b823f5a1 338 M_PENDATA->m_style = Style;
2bda0e17 339
2bda0e17
KB
340 RealizeResource();
341}
342
343void wxPen::SetStipple(const wxBitmap& Stipple)
344{
b823f5a1 345 Unshare();
2bda0e17 346
b823f5a1
JS
347 M_PENDATA->m_stipple = Stipple;
348 M_PENDATA->m_style = wxSTIPPLE;
2bda0e17 349
2bda0e17
KB
350 RealizeResource();
351}
352
debe6624 353void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
2bda0e17 354{
b823f5a1 355 Unshare();
2bda0e17 356
b823f5a1
JS
357 M_PENDATA->m_nbDash = nb_dashes;
358 M_PENDATA->m_dash = (wxDash *)Dash;
2bda0e17 359
2bda0e17
KB
360 RealizeResource();
361}
362
debe6624 363void wxPen::SetJoin(int Join)
2bda0e17 364{
b823f5a1 365 Unshare();
2bda0e17 366
b823f5a1 367 M_PENDATA->m_join = Join;
2bda0e17 368
2bda0e17
KB
369 RealizeResource();
370}
371
debe6624 372void wxPen::SetCap(int Cap)
2bda0e17 373{
b823f5a1 374 Unshare();
2bda0e17 375
b823f5a1 376 M_PENDATA->m_cap = Cap;
2bda0e17 377
2bda0e17
KB
378 RealizeResource();
379}
380
381int wx2msPenStyle(int wx_style)
382{
383 int cstyle;
384/***
385#ifdef __WIN32__
386 DWORD vers = GetVersion() ;
387 WORD high = HIWORD(vers) ; // high bit=0 for NT, 1 for Win32s
388#endif
389***/
390 switch (wx_style)
391 {
392 case wxDOT:
393 cstyle = PS_DOT;
394 break;
395 case wxSHORT_DASH:
396 case wxLONG_DASH:
397 cstyle = PS_DASH;
398 break;
399 case wxTRANSPARENT:
400 cstyle = PS_NULL;
401 break;
402 case wxUSER_DASH:
403 // User dash style not supported on Win3.1, sorry...
404#ifdef __WIN32__
405 // Win32s doesn't have PS_USERSTYLE
406/***
407 if ((high&0x8000)==0)
408***/
409 if (wxGetOsVersion()==wxWINDOWS_NT)
410 cstyle = PS_USERSTYLE ;
411 else
412 cstyle = PS_DOT ; // We must make a choice... This is mine!
413#else
414 cstyle = PS_DASH ;
415#endif
416 break ;
417 case wxSOLID:
418 default:
419 cstyle = PS_SOLID;
420 break;
421 }
422 return cstyle;
423}
424