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