]> git.saurik.com Git - wxWidgets.git/blob - src/os2/pen.cpp
Ensure there is valid context for DrawRectangle
[wxWidgets.git] / src / os2 / pen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/pen.cpp
3 // Purpose: wxPen
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/10/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #include "wx/pen.h"
16
17 #ifndef WX_PRECOMP
18 #include <stdio.h>
19 #include "wx/list.h"
20 #include "wx/utils.h"
21 #include "wx/app.h"
22 #include "wx/log.h"
23 #endif
24
25 #include "wx/os2/private.h"
26
27 class WXDLLIMPEXP_FWD_CORE wxPen;
28
29 // ----------------------------------------------------------------------------
30 // wxPenRefData: contains information about an HPEN and its handle
31 // ----------------------------------------------------------------------------
32
33 class WXDLLEXPORT wxPenRefData: public wxGDIRefData
34 {
35 friend class WXDLLIMPEXP_FWD_CORE wxPen;
36 public:
37 wxPenRefData();
38 wxPenRefData(const wxPenRefData& rData);
39 wxPenRefData(const wxColour& col, int width, wxPenStyle style);
40 wxPenRefData(const wxBitmap& stipple, int width);
41 virtual ~wxPenRefData();
42
43 bool operator==(const wxPenRefData& data) const
44 {
45 // we intentionally don't compare m_hPen fields here
46 return m_nStyle == data.m_nStyle &&
47 m_nWidth == data.m_nWidth &&
48 m_nJoin == data.m_nJoin &&
49 m_nCap == data.m_nCap &&
50 m_vColour == data.m_vColour &&
51 (m_nStyle != wxPENSTYLE_STIPPLE || m_vStipple.IsSameAs(data.m_vStipple)) &&
52 (m_nStyle != wxPENSTYLE_USER_DASH ||
53 (m_dash == data.m_dash &&
54 memcmp(m_dash, data.m_dash, m_nbDash*sizeof(wxDash)) == 0));
55 }
56
57 private:
58 // initialize the fields which have reasonable default values
59 //
60 // doesn't initialize m_width and m_style which must be initialize in ctor
61 void Init()
62 {
63 m_nJoin = wxJOIN_ROUND;
64 m_nCap = wxCAP_ROUND;
65 m_nbDash = 0;
66 m_dash = NULL;
67 m_hPen = 0;
68 }
69
70 int m_nWidth;
71 wxPenStyle m_nStyle;
72 wxPenJoin m_nJoin;
73 wxPenCap m_nCap;
74 wxBitmap m_vStipple;
75 int m_nbDash;
76 wxDash * m_dash;
77 wxColour m_vColour;
78 WXHPEN m_hPen;// in OS/2 GPI this will be the PS the pen is associated with
79
80 wxDECLARE_NO_ASSIGN_CLASS(wxPenRefData);
81 };
82
83 #define M_PENDATA ((wxPenRefData *)m_refData)
84
85 // ----------------------------------------------------------------------------
86 // wxPenRefData ctors/dtor
87 // ----------------------------------------------------------------------------
88
89 wxPenRefData::wxPenRefData()
90 {
91 Init();
92
93 m_nStyle = wxPENSTYLE_SOLID;
94 m_nWidth = 1;
95 } // end of wxPenRefData::wxPenRefData
96
97 wxPenRefData::wxPenRefData(
98 const wxPenRefData& rData
99 )
100 {
101 m_nStyle = rData.m_nStyle;
102 m_nWidth = rData.m_nWidth;
103 m_nJoin = rData.m_nJoin;
104 m_nCap = rData.m_nCap;
105 m_nbDash = rData.m_nbDash;
106 m_dash = rData.m_dash;
107 m_vColour = rData.m_vColour;
108 m_hPen = 0L;
109 } // end of wxPenRefData::wxPenRefData
110
111 wxPenRefData::wxPenRefData(const wxColour& col, int width, wxPenStyle style)
112 {
113 Init();
114
115 m_nStyle = style;
116 m_nWidth = width;
117
118 m_vColour = col;
119 }
120
121 wxPenRefData::wxPenRefData(const wxBitmap& stipple, int width)
122 {
123 Init();
124
125 m_nStyle = wxPENSTYLE_STIPPLE;
126 m_nWidth = width;
127
128 m_vStipple = stipple;
129 }
130
131 wxPenRefData::~wxPenRefData()
132 {
133 } // end of wxPenRefData::~wxPenRefData
134
135 // ----------------------------------------------------------------------------
136 // wxPen
137 // ----------------------------------------------------------------------------
138
139 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
140
141 wxPen::wxPen(
142 const wxColour& rColour
143 , int nWidth
144 , wxPenStyle nStyle
145 )
146 {
147 m_refData = new wxPenRefData(rColour, nWidth, nStyle);
148
149 RealizeResource();
150 } // end of wxPen::wxPen
151
152 #if FUTURE_WXWIN_COMPATIBILITY_3_0
153 wxPen::wxPen(const wxColour& colour, int width, int style)
154 {
155 m_refData = new wxPenRefData(colour, width, (wxPenStyle)style);
156
157 RealizeResource();
158 }
159 #endif
160
161 wxPen::wxPen(
162 const wxBitmap& rStipple
163 , int nWidth
164 )
165 {
166 m_refData = new wxPenRefData (rStipple, nWidth);
167
168 RealizeResource();
169 } // end of wxPen::wxPen
170
171 bool wxPen::operator==(const wxPen& pen) const
172 {
173 const wxPenRefData *
174 penData = static_cast<const wxPenRefData *>(pen.m_refData);
175
176 // an invalid pen is only equal to another invalid pen
177 return m_refData ? penData && *M_PENDATA == *penData : !penData;
178 }
179
180 int wx2os2PenStyle(
181 wxPenStyle nWxStyle
182 );
183
184 bool wxPen::RealizeResource()
185 {
186 BOOL bOk;
187 ERRORID vError;
188 wxString sError;
189
190 if (M_PENDATA && M_PENDATA->m_hPen == 0L)
191 {
192 SIZEL vSize = {0, 0};
193 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
194 HDC hDC = ::DevOpenDC( vHabmain
195 ,OD_MEMORY
196 ,"*"
197 ,5L
198 ,(PDEVOPENDATA)&vDop
199 ,NULLHANDLE
200 );
201 M_PENDATA->m_hPen = (WXHPEN)::GpiCreatePS( vHabmain
202 ,hDC
203 ,&vSize
204 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
205 );
206 }
207 if (M_PENDATA)
208 {
209 //
210 // Set the color table to RGB mode
211 //
212 if (!::GpiCreateLogColorTable( (HPS)M_PENDATA->m_hPen
213 ,0L
214 ,LCOLF_RGB
215 ,0L
216 ,0L
217 ,NULL
218 ))
219 {
220 vError = ::WinGetLastError(vHabmain);
221 sError = wxPMErrorToStr(vError);
222 wxLogError(wxT("Unable to set current color table to RGB mode. Error: %s\n"), sError.c_str());
223 return false;
224 }
225 if (M_PENDATA->m_nStyle == wxPENSTYLE_TRANSPARENT)
226 {
227 return true;
228 }
229
230 COLORREF vPmColour = 0L;
231 USHORT uLineType = (USHORT)wx2os2PenStyle(M_PENDATA->m_nStyle);
232
233 vPmColour = M_PENDATA->m_vColour.GetPixel();
234
235 USHORT uJoin = 0L;
236
237 switch(M_PENDATA->m_nJoin)
238 {
239 case wxJOIN_BEVEL:
240 uJoin = LINEJOIN_BEVEL;
241 break;
242
243 case wxJOIN_MITER:
244 uJoin = LINEJOIN_MITRE;
245 break;
246
247 case wxJOIN_ROUND:
248 uJoin = LINEJOIN_ROUND;
249 break;
250 }
251
252 USHORT uCap = 0L;
253
254 switch(M_PENDATA->m_nCap)
255 {
256 case wxCAP_PROJECTING:
257 uCap = LINEEND_SQUARE;
258 break;
259
260 case wxCAP_BUTT:
261 uCap = LINEEND_FLAT;
262 break;
263
264 case wxCAP_ROUND:
265 uCap = LINEEND_ROUND;
266 break;
267 }
268 m_vLineBundle.lColor = (LONG)vPmColour;
269 m_vLineBundle.usMixMode = FM_OVERPAINT;
270 if (M_PENDATA->m_nWidth < 1)
271 M_PENDATA->m_nWidth = 1;
272 m_vLineBundle.fxWidth = M_PENDATA->m_nWidth;
273 m_vLineBundle.lGeomWidth = M_PENDATA->m_nWidth;
274 m_vLineBundle.usType = uLineType;
275 m_vLineBundle.usEnd = uCap;
276 m_vLineBundle.usJoin = uJoin;
277
278 bOk = ::GpiSetAttrs( M_PENDATA->m_hPen
279 ,PRIM_LINE
280 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE | LBB_END | LBB_JOIN
281 ,0L
282 ,&m_vLineBundle
283 );
284 if (!bOk)
285 {
286 vError = ::WinGetLastError(vHabmain);
287 sError = wxPMErrorToStr(vError);
288 wxLogError(wxT("Can't set Gpi attributes for a LINEBUNDLE. Error: %s\n"), sError.c_str());
289 return false;
290 }
291
292 ULONG flAttrMask = 0L;
293 ULONG flDefMask = 0L;
294 switch(M_PENDATA->m_nStyle)
295 {
296 case wxPENSTYLE_STIPPLE:
297 ::GpiSetBitmapId( M_PENDATA->m_hPen
298 ,(USHORT)M_PENDATA->m_vStipple.GetHBITMAP()
299 ,(USHORT)M_PENDATA->m_vStipple.GetId()
300 );
301 ::GpiSetPatternSet( M_PENDATA->m_hPen
302 ,(USHORT)M_PENDATA->m_vStipple.GetId()
303 );
304 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SET | ABB_SYMBOL;
305 flDefMask = ABB_REF_POINT;
306 break;
307
308 case wxPENSTYLE_BDIAGONAL_HATCH:
309 m_vAreaBundle.usSymbol = PATSYM_DIAG3;
310 m_vAreaBundle.usSet = LCID_DEFAULT;
311 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
312 flDefMask = ABB_SET | ABB_REF_POINT;
313 break;
314
315 case wxPENSTYLE_CROSSDIAG_HATCH:
316 m_vAreaBundle.usSymbol = PATSYM_DIAGHATCH;
317 m_vAreaBundle.usSet = LCID_DEFAULT;
318 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
319 flDefMask = ABB_SET | ABB_REF_POINT;
320 break;
321
322 case wxPENSTYLE_FDIAGONAL_HATCH:
323 m_vAreaBundle.usSymbol = PATSYM_DIAG1;
324 m_vAreaBundle.usSet = LCID_DEFAULT;
325 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
326 flDefMask = ABB_SET | ABB_REF_POINT;
327 break;
328
329 case wxPENSTYLE_CROSS_HATCH:
330 m_vAreaBundle.usSymbol = PATSYM_HATCH;
331 m_vAreaBundle.usSet = LCID_DEFAULT;
332 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
333 flDefMask = ABB_SET | ABB_REF_POINT;
334 break;
335
336 case wxPENSTYLE_HORIZONTAL_HATCH:
337 m_vAreaBundle.usSymbol = PATSYM_HORIZ;
338 m_vAreaBundle.usSet = LCID_DEFAULT;
339 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
340 flDefMask = ABB_SET | ABB_REF_POINT;
341 break;
342
343 case wxPENSTYLE_VERTICAL_HATCH:
344 m_vAreaBundle.usSymbol = PATSYM_VERT;
345 m_vAreaBundle.usSet = LCID_DEFAULT;
346 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
347 flDefMask = ABB_SET | ABB_REF_POINT;
348 break;
349
350 default:
351 m_vAreaBundle.usSymbol = PATSYM_SOLID;
352 m_vAreaBundle.usSet = LCID_DEFAULT;
353 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
354 flDefMask = ABB_SET | ABB_REF_POINT;
355 break;
356 }
357
358 m_vAreaBundle.lColor = vPmColour;
359 m_vAreaBundle.lBackColor = RGB_WHITE;
360 m_vAreaBundle.usMixMode = FM_OVERPAINT;
361 m_vAreaBundle.usBackMixMode = BM_OVERPAINT;
362
363 bOk = ::GpiSetAttrs( M_PENDATA->m_hPen
364 ,PRIM_AREA
365 ,flAttrMask
366 ,flDefMask
367 ,&m_vAreaBundle
368 );
369 if (!bOk)
370 {
371 vError = ::WinGetLastError(vHabmain);
372 sError = wxPMErrorToStr(vError);
373 wxLogError(wxT("Can't set Gpi attributes for an AREABUNDLE. Error: %s\n"), sError.c_str());
374 }
375
376 return (bool)bOk;
377 }
378 return false;
379 } // end of wxPen::RealizeResource
380
381 WXHANDLE wxPen::GetResourceHandle() const
382 {
383 if (!M_PENDATA)
384 return 0;
385 else
386 return (WXHANDLE)M_PENDATA->m_hPen;
387 } // end of wxPen::GetResourceHandle
388
389 bool wxPen::FreeResource( bool WXUNUSED(bForce) )
390 {
391 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
392 {
393 M_PENDATA->m_hPen = 0;
394 return true;
395 }
396 else return false;
397 } // end of wxPen::FreeResource
398
399 bool wxPen::IsFree() const
400 {
401 return (M_PENDATA && M_PENDATA->m_hPen == 0);
402 }
403
404 wxGDIRefData* wxPen::CreateGDIRefData() const
405 {
406 return new wxPenRefData;
407 }
408
409 wxGDIRefData* wxPen::CloneGDIRefData(const wxGDIRefData* data) const
410 {
411 return new wxPenRefData(*static_cast<const wxPenRefData*>(data));
412 }
413
414 void wxPen::SetColour( const wxColour& rColour )
415 {
416 AllocExclusive();
417 M_PENDATA->m_vColour = rColour;
418 RealizeResource();
419 } // end of wxPen::SetColour
420
421 void wxPen::SetColour( unsigned char cRed, unsigned char cGreen, unsigned char cBlue)
422 {
423 AllocExclusive();
424 M_PENDATA->m_vColour.Set(cRed, cGreen, cBlue);
425 RealizeResource();
426 } // end of wxPen::SetColour
427
428 void wxPen::SetPS( HPS hPS )
429 {
430 AllocExclusive();
431 if (M_PENDATA->m_hPen)
432 ::GpiDestroyPS(M_PENDATA->m_hPen);
433 M_PENDATA->m_hPen = hPS;
434 RealizeResource();
435 } // end of WxWinGdi_CPen::SetPS
436
437 void wxPen::SetWidth(
438 int nWidth
439 )
440 {
441 AllocExclusive();
442 M_PENDATA->m_nWidth = nWidth;
443 RealizeResource();
444 } // end of wxPen::SetWidth
445
446 void wxPen::SetStyle(
447 wxPenStyle nStyle
448 )
449 {
450 AllocExclusive();
451 M_PENDATA->m_nStyle = nStyle;
452 RealizeResource();
453 } // end of wxPen::SetStyle
454
455 void wxPen::SetStipple(
456 const wxBitmap& rStipple
457 )
458 {
459 AllocExclusive();
460 M_PENDATA->m_vStipple = rStipple;
461 M_PENDATA->m_nStyle = wxPENSTYLE_STIPPLE;
462 RealizeResource();
463 } // end of wxPen::SetStipple
464
465 void wxPen::SetDashes( int WXUNUSED(nNbDashes),
466 const wxDash* WXUNUSED(pDash) )
467 {
468 //
469 // Does nothing under OS/2
470 //
471 } // end of wxPen::SetDashes
472
473 void wxPen::SetJoin(
474 wxPenJoin nJoin
475 )
476 {
477 AllocExclusive();
478 M_PENDATA->m_nJoin = nJoin;
479 RealizeResource();
480 } // end of wxPen::SetJoin
481
482 void wxPen::SetCap(
483 wxPenCap nCap
484 )
485 {
486 AllocExclusive();
487 M_PENDATA->m_nCap = nCap;
488 RealizeResource();
489 } // end of wxPen::SetCap
490
491 wxColour wxPen::GetColour() const
492 {
493 wxCHECK_MSG( IsOk(), wxNullColour, wxT("invalid pen") );
494
495 return M_PENDATA->m_vColour;
496 }
497
498 int wxPen::GetWidth() const
499 {
500 wxCHECK_MSG( IsOk(), -1, wxT("invalid pen") );
501
502 return M_PENDATA->m_nWidth;
503 }
504
505 wxPenStyle wxPen::GetStyle() const
506 {
507 wxCHECK_MSG( IsOk(), wxPENSTYLE_INVALID, wxT("invalid pen") );
508
509 return M_PENDATA->m_nStyle;
510 }
511
512 wxPenJoin wxPen::GetJoin() const
513 {
514 wxCHECK_MSG( IsOk(), wxJOIN_INVALID, wxT("invalid pen") );
515
516 return M_PENDATA->m_nJoin;
517 }
518
519 wxPenCap wxPen::GetCap() const
520 {
521 wxCHECK_MSG( IsOk(), wxCAP_INVALID, wxT("invalid pen") );
522
523 return M_PENDATA->m_nCap;
524 }
525
526 int wxPen::GetPS() const
527 {
528 wxCHECK_MSG( IsOk(), 0, wxT("invalid pen") );
529
530 return M_PENDATA->m_hPen;
531 }
532
533 int wxPen::GetDashes(wxDash** ptr) const
534 {
535 wxCHECK_MSG( IsOk(), -1, wxT("invalid pen") );
536
537 *ptr = M_PENDATA->m_dash;
538 return M_PENDATA->m_nbDash;
539 }
540
541 wxDash* wxPen::GetDash() const
542 {
543 wxCHECK_MSG( IsOk(), NULL, wxT("invalid pen") );
544
545 return M_PENDATA->m_dash;
546 }
547
548 int wxPen::GetDashCount() const
549 {
550 wxCHECK_MSG( IsOk(), -1, wxT("invalid pen") );
551
552 return M_PENDATA->m_nbDash;
553 }
554
555 wxBitmap* wxPen::GetStipple() const
556 {
557 wxCHECK_MSG( IsOk(), NULL, wxT("invalid pen") );
558
559 return &(M_PENDATA->m_vStipple);
560 }
561
562 int wx2os2PenStyle(
563 wxPenStyle nWxStyle
564 )
565 {
566 int nPMStyle = 0;
567
568 switch (nWxStyle)
569 {
570 case wxPENSTYLE_DOT:
571 nPMStyle = LINETYPE_DOT;
572 break;
573
574 case wxPENSTYLE_DOT_DASH:
575 nPMStyle = LINETYPE_DASHDOT;
576 break;
577
578 case wxPENSTYLE_SHORT_DASH:
579 nPMStyle = LINETYPE_SHORTDASH;
580 break;
581
582 case wxPENSTYLE_LONG_DASH:
583 nPMStyle = LINETYPE_LONGDASH;
584 break;
585
586 case wxPENSTYLE_TRANSPARENT:
587 nPMStyle = LINETYPE_INVISIBLE;
588 break;
589
590 case wxPENSTYLE_USER_DASH:
591 nPMStyle = LINETYPE_DASHDOUBLEDOT; // We must make a choice... This is mine!
592 break;
593
594 case wxPENSTYLE_SOLID:
595 default:
596 nPMStyle = LINETYPE_SOLID;
597 break;
598 }
599 return nPMStyle;
600 } // end of wx2os2PenStyle