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