make the Pen/Brush code backward compatible as discussed on wx-dev; marked the blocks...
[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 #include "assert.h"
27
28 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
29
30 wxPenRefData::wxPenRefData()
31 {
32 m_nStyle = wxPENSTYLE_SOLID;
33 m_nWidth = 1;
34 m_nJoin = wxJOIN_ROUND ;
35 m_nCap = wxCAP_ROUND ;
36 m_nbDash = 0 ;
37 m_dash = (wxDash*)NULL;
38 m_hPen = 0L;
39 } // end of wxPenRefData::wxPenRefData
40
41 wxPenRefData::wxPenRefData(
42 const wxPenRefData& rData
43 )
44 {
45 m_nStyle = rData.m_nStyle;
46 m_nWidth = rData.m_nWidth;
47 m_nJoin = rData.m_nJoin;
48 m_nCap = rData.m_nCap;
49 m_nbDash = rData.m_nbDash;
50 m_dash = rData.m_dash;
51 m_vColour = rData.m_vColour;
52 m_hPen = 0L;
53 } // end of wxPenRefData::wxPenRefData
54
55 wxPenRefData::~wxPenRefData()
56 {
57 } // end of wxPenRefData::~wxPenRefData
58
59 //
60 // Pens
61 //
62 wxPen::wxPen()
63 {
64 } // end of wxPen::wxPen
65
66 wxPen::~wxPen()
67 {
68 } // end of wxPen::wxPen
69
70 // Should implement Create
71 wxPen::wxPen(
72 const wxColour& rColour
73 , int nWidth
74 , wxPenStyle nStyle
75 )
76 {
77 m_refData = new wxPenRefData;
78
79 M_PENDATA->m_vColour = rColour;
80 M_PENDATA->m_nWidth = nWidth;
81 M_PENDATA->m_nStyle = nStyle;
82 M_PENDATA->m_nJoin = wxJOIN_ROUND ;
83 M_PENDATA->m_nCap = wxCAP_ROUND ;
84 M_PENDATA->m_hPen = 0L;
85
86 RealizeResource();
87 } // end of wxPen::wxPen
88
89 #if FUTURE_WXWIN_COMPATIBILITY_3_0
90 wxPen::wxPen(const wxColour& colour, int width, int style)
91 {
92 m_refData = new wxPenRefData;
93
94 M_PENDATA->m_vColour = colour;
95 M_PENDATA->m_nWidth = width;
96 M_PENDATA->m_nStyle = (wxPenStyle)nStyle;
97 M_PENDATA->m_nJoin = wxJOIN_ROUND ;
98 M_PENDATA->m_nCap = wxCAP_ROUND ;
99 M_PENDATA->m_hPen = 0L;
100
101 RealizeResource();
102 }
103 #endif
104
105 wxPen::wxPen(
106 const wxBitmap& rStipple
107 , int nWidth
108 )
109 {
110 m_refData = new wxPenRefData;
111
112 M_PENDATA->m_vStipple = rStipple;
113 M_PENDATA->m_nWidth = nWidth;
114 M_PENDATA->m_nStyle = wxSTIPPLE;
115 M_PENDATA->m_nJoin = wxJOIN_ROUND ;
116 M_PENDATA->m_nCap = wxCAP_ROUND ;
117 M_PENDATA->m_hPen = 0;
118
119 RealizeResource();
120 } // end of wxPen::wxPen
121
122 int wx2os2PenStyle(
123 wxPenStyle nWxStyle
124 );
125
126 bool wxPen::RealizeResource()
127 {
128 BOOL bOk;
129 ERRORID vError;
130 wxString sError;
131
132 if (M_PENDATA && M_PENDATA->m_hPen == 0L)
133 {
134 SIZEL vSize = {0, 0};
135 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
136 HDC hDC = ::DevOpenDC( vHabmain
137 ,OD_MEMORY
138 ,"*"
139 ,5L
140 ,(PDEVOPENDATA)&vDop
141 ,NULLHANDLE
142 );
143 M_PENDATA->m_hPen = (WXHPEN)::GpiCreatePS( vHabmain
144 ,hDC
145 ,&vSize
146 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
147 );
148 }
149 if (M_PENDATA)
150 {
151 //
152 // Set the color table to RGB mode
153 //
154 if (!::GpiCreateLogColorTable( (HPS)M_PENDATA->m_hPen
155 ,0L
156 ,LCOLF_RGB
157 ,0L
158 ,0L
159 ,NULL
160 ))
161 {
162 vError = ::WinGetLastError(vHabmain);
163 sError = wxPMErrorToStr(vError);
164 wxLogError(_T("Unable to set current color table to RGB mode. Error: %s\n"), sError.c_str());
165 return false;
166 }
167 if (M_PENDATA->m_nStyle == wxPENSTYLE_TRANSPARENT)
168 {
169 return true;
170 }
171
172 COLORREF vPmColour = 0L;
173 USHORT uLineType = (USHORT)wx2os2PenStyle(M_PENDATA->m_nStyle);
174
175 vPmColour = M_PENDATA->m_vColour.GetPixel();
176
177 USHORT uJoin = 0L;
178
179 switch(M_PENDATA->m_nJoin)
180 {
181 case wxJOIN_BEVEL:
182 uJoin = LINEJOIN_BEVEL;
183 break;
184
185 case wxJOIN_MITER:
186 uJoin = LINEJOIN_MITRE;
187 break;
188
189 case wxJOIN_ROUND:
190 uJoin = LINEJOIN_ROUND;
191 break;
192 }
193
194 USHORT uCap = 0L;
195
196 switch(M_PENDATA->m_nCap)
197 {
198 case wxCAP_PROJECTING:
199 uCap = LINEEND_SQUARE;
200 break;
201
202 case wxCAP_BUTT:
203 uCap = LINEEND_FLAT;
204 break;
205
206 case wxCAP_ROUND:
207 uCap = LINEEND_ROUND;
208 break;
209 }
210 m_vLineBundle.lColor = (LONG)vPmColour;
211 m_vLineBundle.usMixMode = FM_OVERPAINT;
212 if (M_PENDATA->m_nWidth < 1)
213 M_PENDATA->m_nWidth = 1;
214 m_vLineBundle.fxWidth = M_PENDATA->m_nWidth;
215 m_vLineBundle.lGeomWidth = M_PENDATA->m_nWidth;
216 m_vLineBundle.usType = uLineType;
217 m_vLineBundle.usEnd = uCap;
218 m_vLineBundle.usJoin = uJoin;
219
220 bOk = ::GpiSetAttrs( M_PENDATA->m_hPen
221 ,PRIM_LINE
222 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE | LBB_END | LBB_JOIN
223 ,0L
224 ,&m_vLineBundle
225 );
226 if (!bOk)
227 {
228 vError = ::WinGetLastError(vHabmain);
229 sError = wxPMErrorToStr(vError);
230 wxLogError(_T("Can't set Gpi attributes for a LINEBUNDLE. Error: %s\n"), sError.c_str());
231 return false;
232 }
233
234 ULONG flAttrMask = 0L;
235 ULONG flDefMask = 0L;
236 switch(M_PENDATA->m_nStyle)
237 {
238 case wxPENSTYLE_STIPPLE:
239 ::GpiSetBitmapId( M_PENDATA->m_hPen
240 ,(USHORT)M_PENDATA->m_vStipple.GetHBITMAP()
241 ,(USHORT)M_PENDATA->m_vStipple.GetId()
242 );
243 ::GpiSetPatternSet( M_PENDATA->m_hPen
244 ,(USHORT)M_PENDATA->m_vStipple.GetId()
245 );
246 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SET | ABB_SYMBOL;
247 flDefMask = ABB_REF_POINT;
248 break;
249
250 case wxPENSTYLE_BDIAGONAL_HATCH:
251 m_vAreaBundle.usSymbol = PATSYM_DIAG3;
252 m_vAreaBundle.usSet = LCID_DEFAULT;
253 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
254 flDefMask = ABB_SET | ABB_REF_POINT;
255 break;
256
257 case wxPENSTYLE_CROSSDIAG_HATCH:
258 m_vAreaBundle.usSymbol = PATSYM_DIAGHATCH;
259 m_vAreaBundle.usSet = LCID_DEFAULT;
260 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
261 flDefMask = ABB_SET | ABB_REF_POINT;
262 break;
263
264 case wxPENSTYLE_FDIAGONAL_HATCH:
265 m_vAreaBundle.usSymbol = PATSYM_DIAG1;
266 m_vAreaBundle.usSet = LCID_DEFAULT;
267 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
268 flDefMask = ABB_SET | ABB_REF_POINT;
269 break;
270
271 case wxPENSTYLE_CROSS_HATCH:
272 m_vAreaBundle.usSymbol = PATSYM_HATCH;
273 m_vAreaBundle.usSet = LCID_DEFAULT;
274 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
275 flDefMask = ABB_SET | ABB_REF_POINT;
276 break;
277
278 case wxPENSTYLE_HORIZONTAL_HATCH:
279 m_vAreaBundle.usSymbol = PATSYM_HORIZ;
280 m_vAreaBundle.usSet = LCID_DEFAULT;
281 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
282 flDefMask = ABB_SET | ABB_REF_POINT;
283 break;
284
285 case wxPENSTYLE_VERTICAL_HATCH:
286 m_vAreaBundle.usSymbol = PATSYM_VERT;
287 m_vAreaBundle.usSet = LCID_DEFAULT;
288 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
289 flDefMask = ABB_SET | ABB_REF_POINT;
290 break;
291
292 default:
293 m_vAreaBundle.usSymbol = PATSYM_SOLID;
294 m_vAreaBundle.usSet = LCID_DEFAULT;
295 flAttrMask = ABB_COLOR | ABB_BACK_COLOR | ABB_MIX_MODE | ABB_BACK_MIX_MODE | ABB_SYMBOL;
296 flDefMask = ABB_SET | ABB_REF_POINT;
297 break;
298 }
299
300 m_vAreaBundle.lColor = vPmColour;
301 m_vAreaBundle.lBackColor = RGB_WHITE;
302 m_vAreaBundle.usMixMode = FM_OVERPAINT;
303 m_vAreaBundle.usBackMixMode = BM_OVERPAINT;
304
305 bOk = ::GpiSetAttrs( M_PENDATA->m_hPen
306 ,PRIM_AREA
307 ,flAttrMask
308 ,flDefMask
309 ,&m_vAreaBundle
310 );
311 if (!bOk)
312 {
313 vError = ::WinGetLastError(vHabmain);
314 sError = wxPMErrorToStr(vError);
315 wxLogError(_T("Can't set Gpi attributes for an AREABUNDLE. Error: %s\n"), sError.c_str());
316 }
317
318 return (bool)bOk;
319 }
320 return false;
321 } // end of wxPen::RealizeResource
322
323 WXHANDLE wxPen::GetResourceHandle() const
324 {
325 if (!M_PENDATA)
326 return 0;
327 else
328 return (WXHANDLE)M_PENDATA->m_hPen;
329 } // end of wxPen::GetResourceHandle
330
331 bool wxPen::FreeResource( bool WXUNUSED(bForce) )
332 {
333 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
334 {
335 M_PENDATA->m_hPen = 0;
336 return true;
337 }
338 else return false;
339 } // end of wxPen::FreeResource
340
341 bool wxPen::IsFree() const
342 {
343 return (M_PENDATA && M_PENDATA->m_hPen == 0);
344 }
345
346 wxGDIRefData* wxPen::CreateGDIRefData() const
347 {
348 return new wxPenRefData;
349 }
350
351 wxGDIRefData* wxPen::CloneGDIRefData(const wxGDIRefData* data) const
352 {
353 return new wxPenRefData(*wx_static_cast(const wxPenRefData*, data));
354 }
355
356 void wxPen::SetColour( const wxColour& rColour )
357 {
358 AllocExclusive();
359 M_PENDATA->m_vColour = rColour;
360 RealizeResource();
361 } // end of wxPen::SetColour
362
363 void wxPen::SetColour( unsigned char cRed, unsigned char cGreen, unsigned char cBlue)
364 {
365 AllocExclusive();
366 M_PENDATA->m_vColour.Set(cRed, cGreen, cBlue);
367 RealizeResource();
368 } // end of wxPen::SetColour
369
370 void wxPen::SetPS( HPS hPS )
371 {
372 AllocExclusive();
373 if (M_PENDATA->m_hPen)
374 ::GpiDestroyPS(M_PENDATA->m_hPen);
375 M_PENDATA->m_hPen = hPS;
376 RealizeResource();
377 } // end of WxWinGdi_CPen::SetPS
378
379 void wxPen::SetWidth(
380 int nWidth
381 )
382 {
383 AllocExclusive();
384 M_PENDATA->m_nWidth = nWidth;
385 RealizeResource();
386 } // end of wxPen::SetWidth
387
388 void wxPen::SetStyle(
389 wxPenStyle nStyle
390 )
391 {
392 AllocExclusive();
393 M_PENDATA->m_nStyle = nStyle;
394 RealizeResource();
395 } // end of wxPen::SetStyle
396
397 void wxPen::SetStipple(
398 const wxBitmap& rStipple
399 )
400 {
401 AllocExclusive();
402 M_PENDATA->m_vStipple = rStipple;
403 M_PENDATA->m_nStyle = wxSTIPPLE;
404 RealizeResource();
405 } // end of wxPen::SetStipple
406
407 void wxPen::SetDashes( int WXUNUSED(nNbDashes),
408 const wxDash* WXUNUSED(pDash) )
409 {
410 //
411 // Does nothing under OS/2
412 //
413 } // end of wxPen::SetDashes
414
415 void wxPen::SetJoin(
416 wxPenJoin nJoin
417 )
418 {
419 AllocExclusive();
420 M_PENDATA->m_nJoin = nJoin;
421 RealizeResource();
422 } // end of wxPen::SetJoin
423
424 void wxPen::SetCap(
425 wxPenCap nCap
426 )
427 {
428 AllocExclusive();
429 M_PENDATA->m_nCap = nCap;
430 RealizeResource();
431 } // end of wxPen::SetCap
432
433 int wx2os2PenStyle(
434 wxPenStyle nWxStyle
435 )
436 {
437 int nPMStyle = 0;
438
439 switch (nWxStyle)
440 {
441 case wxPENSTYLE_DOT:
442 nPMStyle = LINETYPE_DOT;
443 break;
444
445 case wxPENSTYLE_DOT_DASH:
446 nPMStyle = LINETYPE_DASHDOT;
447 break;
448
449 case wxPENSTYLE_SHORT_DASH:
450 nPMStyle = LINETYPE_SHORTDASH;
451 break;
452
453 case wxPENSTYLE_LONG_DASH:
454 nPMStyle = LINETYPE_LONGDASH;
455 break;
456
457 case wxPENSTYLE_TRANSPARENT:
458 nPMStyle = LINETYPE_INVISIBLE;
459 break;
460
461 case wxPENSTYLE_USER_DASH:
462 nPMStyle = LINETYPE_DASHDOUBLEDOT; // We must make a choice... This is mine!
463 break;
464
465 case wxPENSTYLE_SOLID:
466 default:
467 nPMStyle = LINETYPE_SOLID;
468 break;
469 }
470 return nPMStyle;
471 } // end of wx2os2PenStyle