Files
wxWidgets/src/os2/region.cpp
Vadim Zeitlin 3f66f6a5b3 Remove all lines containing cvs/svn "$Id$" keyword.
This keyword is not expanded by Git which means it's not replaced with the
correct revision value in the releases made using git-based scripts and it's
confusing to have lines with unexpanded "$Id$" in the released files. As
expanding them with Git is not that simple (it could be done with git archive
and export-subst attribute) and there are not many benefits in having them in
the first place, just remove all these lines.

If nothing else, this will make an eventual transition to Git simpler.

Closes #14487.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-07-26 16:02:46 +00:00

659 lines
20 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// File: src/os2/region.cpp
// Purpose: Region class
// Author: David Webster
// Modified by:
// Created: 10/15/99
// Copyright: (c) David Webster
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/window.h"
#include "wx/gdicmn.h"
#endif
#include "wx/os2/region.h"
#include "wx/os2/private.h"
IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
//-----------------------------------------------------------------------------
// wxRegionRefData implementation
//-----------------------------------------------------------------------------
class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
public:
wxRegionRefData()
{
m_hRegion = 0;
m_hPS = 0;
}
wxRegionRefData(const wxRegionRefData& rData)
{
RGNRECT vRgnData;
PRECTL pRect = NULL;
vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
if (::GpiQueryRegionRects( rData.m_hPS // Pres space
,rData.m_hRegion // Handle of region to query
,NULL // Return all RECTs
,&vRgnData // Will contain number or RECTs in region
,NULL // NULL to return number of RECTs
))
{
pRect = new RECTL[vRgnData.crcReturned];
vRgnData.crc = vRgnData.crcReturned;
vRgnData.ircStart = 1;
if (::GpiQueryRegionRects( rData.m_hPS // Pres space of source
,rData.m_hRegion // Handle of source region
,NULL // Return all RECTs
,&vRgnData // Operations set to return rects
,pRect // Will contain the actual RECTS
))
{
m_hRegion = ::GpiCreateRegion( rData.m_hPS
,vRgnData.crcReturned
,pRect
);
m_hPS = rData.m_hPS;
}
delete [] pRect;
}
}
virtual ~wxRegionRefData()
{
::GpiDestroyRegion(m_hPS, m_hRegion);
}
HRGN m_hRegion;
HPS m_hPS;
};
#define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion)
#define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_hRegion)
//-----------------------------------------------------------------------------
// wxRegion
//-----------------------------------------------------------------------------
// General remark:
// wxRegion is always basically stored in wx coordinates. However, since
// OS/2's internal functions rely on "top > bottom", the values of top and
// bottom values of a region need to be interchanged, as compared to wx.
// This needs to be taken into account when feeding any rectangle to wx _or_
// when accessing the region data via GetBox, wxRegionIterator or otherwise.
/*!
* Create an empty region.
*/
wxRegion::wxRegion()
{
m_refData = new wxRegionRefData;
} // end of wxRegion::wxRegion
wxRegion::wxRegion(
WXHRGN hRegion,
WXHDC hPS
)
{
m_refData = new wxRegionRefData;
M_REGION = (HRGN) hRegion;
(((wxRegionRefData*)m_refData)->m_hPS) = hPS;
} // end of wxRegion::wxRegion
wxRegion::wxRegion(
wxCoord x
, wxCoord y
, wxCoord vWidth
, wxCoord vHeight
)
{
RECTL vRect;
SIZEL vSize = {0, 0};
DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
HDC hDC = ::DevOpenDC( vHabmain
,OD_MEMORY
,"*"
,5L
,(PDEVOPENDATA)&vDop
,NULLHANDLE
);
vRect.xLeft = x;
vRect.xRight = x + vWidth;
vRect.yBottom = y;
vRect.yTop = y + vHeight;
m_refData = new wxRegionRefData;
//
// Need a PS to create a Region
//
((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
,hDC
,&vSize
,PU_PELS | GPIT_MICRO | GPIA_ASSOC
);
M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
,1
,&vRect
);
} // end of wxRegion::wxRegion
wxRegion::wxRegion(const wxPoint& rTopLeft,
const wxPoint& rBottomRight)
{
RECTL vRect;
SIZEL vSize = {0, 0};
DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
HDC hDC = ::DevOpenDC( vHabmain
,OD_MEMORY
,"*"
,5L
,(PDEVOPENDATA)&vDop
,NULLHANDLE
);
vRect.xLeft = rTopLeft.x;
vRect.xRight = rBottomRight.x;
vRect.yBottom = rTopLeft.y;
vRect.yTop = rBottomRight.y;
m_refData = new wxRegionRefData;
//
// Need a PS to create a Region
//
((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
,hDC
,&vSize
,PU_PELS | GPIT_MICRO | GPIA_ASSOC
);
M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
,1
,&vRect
);
} // end of wxRegion::wxRegion
wxRegion::wxRegion(const wxRect& rRect)
{
RECTL vRect;
SIZEL vSize = {0, 0};
DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
HDC hDC = ::DevOpenDC( vHabmain
,OD_MEMORY
,"*"
,5L
,(PDEVOPENDATA)&vDop
,NULLHANDLE
);
vRect.xLeft = rRect.x;
vRect.xRight = rRect.x + rRect.width;
vRect.yBottom = rRect.y;
vRect.yTop = rRect.y + rRect.height;
m_refData = new wxRegionRefData;
//
// Need a PS to create a Region
//
((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
,hDC
,&vSize
,PU_PELS | GPIT_MICRO | GPIA_ASSOC
);
M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
,1
,&vRect
);
} // end of wxRegion::wxRegion
wxRegion::wxRegion(size_t n, const wxPoint *points, wxPolygonFillMode WXUNUSED(fillStyle))
{
// TO DO
}
//
// Destroy the region.
//
wxRegion::~wxRegion()
{
} // end of wxRegion::~wxRegion
wxGDIRefData *wxRegion::CreateGDIRefData() const
{
return new wxRegionRefData;
}
wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxRegionRefData(*(wxRegionRefData *)data);
}
//-----------------------------------------------------------------------------
//# Modify region
//-----------------------------------------------------------------------------
bool wxRegion::DoOffset( wxCoord x, wxCoord y )
{
if ( !x && !y )
{
// nothing to do
return true;
}
AllocExclusive();
#if 0
if ( ::OffsetRgn(GetHrgn(), x, y) == ERROR )
{
wxLogLastError(wxT("OffsetRgn"));
return false;
}
#endif
return true;
}
//
// Clear current region
//
void wxRegion::Clear()
{
UnRef();
} // end of wxRegion::Clear
//
// Union region with this.
//
bool wxRegion::DoCombine( const wxRegion& rRegion, wxRegionOp eOp )
{
//
// We can't use the API functions if we don't have a valid region handle
//
if (!m_refData)
{
// combining with an empty/invalid region works differently depending
// on the operation
switch (eOp)
{
case wxRGN_COPY:
case wxRGN_OR:
case wxRGN_XOR:
*this = rRegion;
break;
default:
wxFAIL_MSG( wxT("unknown region operation") );
// fall through
case wxRGN_AND:
case wxRGN_DIFF:
// leave empty/invalid
return false;
}
}
else // we have a valid region
{
LONG lMode = 0;
switch (eOp)
{
case wxRGN_AND:
lMode = CRGN_AND;
break;
case wxRGN_OR:
lMode = CRGN_OR;
break;
case wxRGN_XOR:
lMode = CRGN_XOR;
break;
case wxRGN_DIFF:
lMode = CRGN_DIFF;
break;
case wxRGN_COPY:
default:
lMode = CRGN_COPY;
break;
}
return (::GpiCombineRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
,M_REGION
,M_REGION
,((wxRegionRefData*)rRegion.m_refData)->m_hRegion
,lMode
) != RGN_ERROR);
}
return true;
} // end of wxRegion::Combine
//-----------------------------------------------------------------------------
//# Information on region
//-----------------------------------------------------------------------------
bool wxRegion::DoIsEqual(const wxRegion& WXUNUSED(region)) const
{
return false;
}
//
// Outer bounds of region
//
bool wxRegion::DoGetBox(
wxCoord& x
, wxCoord& y
, wxCoord& vWidth
, wxCoord& vHeight
) const
{
if (m_refData)
{
RECTL vRect;
APIRET rc;
rc = ::GpiQueryRegionBox( ((wxRegionRefData*)m_refData)->m_hPS
,M_REGION
,&vRect
);
x = vRect.xLeft;
y = vRect.yBottom;
vWidth = vRect.xRight - vRect.xLeft;
vHeight = vRect.yTop - vRect.yBottom;
return true;
}
else
{
x = y = vWidth = vHeight = 0L;
return false;
}
} // end of wxRegion::GetBox
//
// Is region empty?
//
bool wxRegion::IsEmpty() const
{
wxCoord x;
wxCoord y;
wxCoord vWidth;
wxCoord vHeight;
if (M_REGION == 0)
return true;
GetBox( x
,y
,vWidth
,vHeight
);
return ((vWidth == 0) && (vHeight == 0));
} // end of wxRegion::IsEmpty
//-----------------------------------------------------------------------------
// Tests
//-----------------------------------------------------------------------------
//
// Does the region contain the point pt?
//
wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const
{
POINTL vPoint = { x, y };
if (!m_refData)
return wxOutRegion;
LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS,
M_REGION,
&vPoint
);
if (lInside == PRGN_INSIDE)
return wxInRegion;
else
return wxOutRegion;
} // end of wxRegion::Contains
//
// Does the region contain the rectangle (x, y, w, h)?
//
wxRegionContain wxRegion::DoContainsRect(const wxRect& rect) const
{
if (!m_refData)
return wxOutRegion;
RECTL vRect;
vRect.xLeft = rect.x;
vRect.xRight = rect.x + rect.width;
vRect.yTop = rect.y + rect.height;
vRect.yBottom = rect.y;
LONG lInside = ::GpiRectInRegion( ((wxRegionRefData*)m_refData)->m_hPS,
M_REGION,
&vRect
);
switch (lInside)
{
case RRGN_INSIDE : return wxInRegion;
case RRGN_PARTIAL : return wxPartRegion;
case RRGN_ERROR :
default : return wxOutRegion;
}
} // end of wxRegion::Contains
//
// Get internal region handle
//
WXHRGN wxRegion::GetHRGN() const
{
if (!m_refData)
return (WXHRGN) 0;
return (WXHRGN) M_REGION;
}
//
// Set a new PS, this means we have to recreate the old region in the new
// PS
//
void wxRegion::SetPS(
HPS hPS
)
{
RGNRECT vRgnData;
PRECTL pRect = NULL;
vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
,((wxRegionRefData*)m_refData)->m_hRegion
,NULL
,&vRgnData
,NULL
))
{
pRect = new RECTL[vRgnData.crcReturned];
vRgnData.crc = vRgnData.crcReturned;
vRgnData.ircStart = 1;
if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
,((wxRegionRefData*)m_refData)->m_hRegion
,NULL
,&vRgnData
,pRect
))
{
//
// First destroy the region out of the old PS
// and then create it in the new and set the new to current
//
::GpiDestroyRegion( ((wxRegionRefData*)m_refData)->m_hPS
,M_REGION
);
((wxRegionRefData*)m_refData)->m_hRegion = ::GpiCreateRegion( hPS
,vRgnData.crcReturned
,pRect
);
((wxRegionRefData*)m_refData)->m_hPS = hPS;
}
delete [] pRect;
}
} // end of wxRegion::SetPS
///////////////////////////////////////////////////////////////////////////////
// //
// wxRegionIterator //
// //
///////////////////////////////////////////////////////////////////////////////
//
// Initialize empty iterator
//
wxRegionIterator::wxRegionIterator()
: m_lCurrent(0)
, m_lNumRects(0)
, m_pRects(NULL)
{
} // end of wxRegionIterator::wxRegionIterator
wxRegionIterator::~wxRegionIterator()
{
if (m_pRects)
delete[] m_pRects;
} // end of wxRegionIterator::~wxRegionIterator
//
// Initialize iterator for region
//
wxRegionIterator::wxRegionIterator(
const wxRegion& rRegion
)
{
m_pRects = NULL;
Reset(rRegion);
} // end of wxRegionIterator::wxRegionIterator
//
// Reset iterator for a new /e region.
//
void wxRegionIterator::Reset(
const wxRegion& rRegion
)
{
m_lCurrent = 0;
m_lNumRects = 0;
m_vRegion = rRegion;
if (m_pRects)
delete[] m_pRects;
m_pRects = NULL;
if (m_vRegion.Empty())
m_lNumRects = 0;
else
{
RGNRECT vRgnData;
PRECTL pRect;
vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space
,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of region to query
,NULL // Return all RECTs
,&vRgnData // Will contain number or RECTs in region
,NULL // NULL to return number of RECTs
))
{
pRect = new RECTL[vRgnData.crcReturned];
m_pRects = new wxRect[vRgnData.crcReturned];
vRgnData.crc = vRgnData.crcReturned;
m_lNumRects = vRgnData.crcReturned;
vRgnData.ircStart = 1;
if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space of source
,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of source region
,NULL // Return all RECTs
,&vRgnData // Operations set to return rects
,pRect // Will contain the actual RECTS
))
{
#if 0
M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
,vRgnData.crcReturned
,pRect
);
#endif
for( LONG i = 0; i < m_lNumRects; i++)
{
m_pRects[i].x = pRect[i].xLeft;
m_pRects[i].width = pRect[i].xRight - pRect[i].xLeft;
m_pRects[i].y = pRect[i].yBottom;
m_pRects[i].height = pRect[i].yTop - pRect[i].yBottom;
}
#if 0
((wxRegionRefData*)m_refData)->m_hPS = ((wxRegionRefData*)rRegion.m_refData)->m_hPS;
#endif
}
}
}
} // end of wxRegionIterator::Reset
//
// Increment iterator. The rectangle returned is the one after the
// incrementation.
//
void wxRegionIterator::operator++ ()
{
if (m_lCurrent < m_lNumRects)
++m_lCurrent;
} // end of wxRegionIterator::operator ++
//
// Increment iterator. The rectangle returned is the one before the
// incrementation.
//
void wxRegionIterator::operator++ (int)
{
if (m_lCurrent < m_lNumRects)
++m_lCurrent;
} // end of wxRegionIterator::operator++
wxCoord wxRegionIterator::GetX() const
{
if (m_lCurrent < m_lNumRects)
return m_pRects[m_lCurrent].x;
return 0L;
} // end of wxRegionIterator::GetX
wxCoord wxRegionIterator::GetY() const
{
if (m_lCurrent < m_lNumRects)
return m_pRects[m_lCurrent].y;
return 0L;
} // end of wxRegionIterator::GetY
wxCoord wxRegionIterator::GetW() const
{
if (m_lCurrent < m_lNumRects)
return m_pRects[m_lCurrent].width ;
return 0L;
} // end of wxRegionIterator::GetW
wxCoord wxRegionIterator::GetH() const
{
if (m_lCurrent < m_lNumRects)
return m_pRects[m_lCurrent].height;
return 0L;
} // end of wxRegionIterator::GetH