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