X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5fd2b2c6ae663c7840f53e4cf087525602eaca7b..d07f2e19181bc5caf29eb2338ce513be6fa42405:/src/os2/dc.cpp?ds=inline diff --git a/src/os2/dc.cpp b/src/os2/dc.cpp index 883aa74a06..b13314253a 100644 --- a/src/os2/dc.cpp +++ b/src/os2/dc.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: dc.cpp +// Name: src/os2/dc.cpp // Purpose: wxDC class // Author: David Webster // Modified by: @@ -23,34 +23,36 @@ #include "wx/log.h" #include "wx/icon.h" #include "wx/msgdlg.h" + #include "wx/dcprint.h" + #include "wx/statusbr.h" + #include "wx/module.h" #endif -#include "wx/dcprint.h" - #include -#include +#include "wx/os2/dc.h" +#include "wx/os2/dcclient.h" #include "wx/os2/private.h" - IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) +IMPLEMENT_ABSTRACT_CLASS(wxPMDCImpl, wxDCImpl) // -// wxWindows uses the Microsoft convention that the origin is the UPPER left. +// wxWidgets uses the Microsoft convention that the origin is the UPPER left. // Native OS/2 however in the GPI and PM define the origin as the LOWER left. -// In order to map OS/2 GPI/PM y coordinates to wxWindows coordinates we must +// In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must // perform the following transformation: // // Parent object height: POBJHEIGHT // Desried origin: WXORIGINY // Object to place's height: OBJHEIGHT // -// To get the OS2 position from the wxWindows one: +// To get the OS2 position from the wxWidgets one: // // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) // // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the // OS/2 Presentation Space associated with the device context. y is the -// desired application's y coordinate of the origin in wxWindows space. +// desired application's y coordinate of the origin in wxWidgets space. // objy is the height of the object we are going to draw. // #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) @@ -64,11 +66,6 @@ static const int VIEWPORT_EXTENT = 1000; static const int MM_POINTS = 9; static const int MM_METRIC = 10; -// usually this is defined in math.h -#ifndef M_PI - static const double M_PI = 3.14159265358979323846; -#endif // M_PI - // --------------------------------------------------------------------------- // private functions // --------------------------------------------------------------------------- @@ -149,29 +146,204 @@ int SetBkMode( // implementation // =========================================================================== +#if wxUSE_DC_CACHEING + +/* + * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will + * improve it in due course, either using arrays, or simply storing pointers to one + * entry for the bitmap, and two for the DCs. -- JACS + */ + // --------------------------------------------------------------------------- -// wxDC +// wxDCCacheEntry // --------------------------------------------------------------------------- -wxDC::wxDC(void) +wxList wxPMDCImpl::m_svBitmapCache; +wxList wxPMDCImpl::m_svDCCache; + +wxDCCacheEntry::wxDCCacheEntry( + WXHBITMAP hBitmap +, int nWidth +, int nHeight +, int nDepth +) +{ + m_hBitmap = hBitmap; + m_hPS = NULLHANDLE; + m_nWidth = nWidth; + m_nHeight = nHeight; + m_nDepth = nDepth; +} // end of wxDCCacheEntry::wxDCCacheEntry + +wxDCCacheEntry::wxDCCacheEntry( + HPS hPS +, int nDepth +) +{ + m_hBitmap = NULLHANDLE; + m_hPS = hPS; + m_nWidth = 0; + m_nHeight = 0; + m_nDepth = nDepth; +} // end of wxDCCacheEntry::wxDCCacheEntry + +wxDCCacheEntry::~wxDCCacheEntry() +{ + if (m_hBitmap) + ::GpiDeleteBitmap(m_hBitmap); + if (m_hPS) + ::GpiDestroyPS(m_hPS); +} // end of wxDCCacheEntry::~wxDCCacheEntry + +wxDCCacheEntry* wxPMDCImpl::FindBitmapInCache( + HPS hPS +, int nWidth +, int nHeight +) +{ + int nDepth = 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); + wxNode* pNode = m_svBitmapCache.First(); + BITMAPINFOHEADER2 vBmpHdr; + + while(pNode) + { + wxDCCacheEntry* pEntry = (wxDCCacheEntry*)pNode->Data(); + + if (pEntry->m_nDepth == nDepth) + { + memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2)); + + if (pEntry->m_nWidth < nWidth || pEntry->m_nHeight < nHeight) + { + ::GpiDeleteBitmap((HBITMAP)pEntry->m_hBitmap); + vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2); + vBmpHdr.cx = nWidth; + vBmpHdr.cy = nHeight; + vBmpHdr.cPlanes = 1; + vBmpHdr.cBitCount = (USHORT)nDepth; + + pEntry->m_hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS + ,&vBmpHdr + ,0L, NULL, NULL + ); + if (!pEntry->m_hBitmap) + { + wxLogLastError(wxT("CreateCompatibleBitmap")); + } + pEntry->m_nWidth = nWidth; + pEntry->m_nHeight = nHeight; + return pEntry; + } + return pEntry; + } + pNode = pNode->Next(); + } + memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2)); + vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2); + vBmpHdr.cx = nWidth; + vBmpHdr.cy = nHeight; + vBmpHdr.cPlanes = 1; + vBmpHdr.cBitCount = (USHORT)nDepth; + + WXHBITMAP hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS + ,&vBmpHdr + ,0L, NULL, NULL + ); + if (!hBitmap) + { + wxLogLastError(wxT("CreateCompatibleBitmap")); + } + wxDCCacheEntry* pEntry = new wxDCCacheEntry( hBitmap + ,nWidth + ,nHeight + ,nDepth + ); + AddToBitmapCache(pEntry); + return pEntry; +} // end of FindBitmapInCache + +wxDCCacheEntry* wxPMDCImpl::FindDCInCache( + wxDCCacheEntry* pNotThis +, HPS hPS +) +{ + int nDepth = 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); + wxNode* pNode = m_svDCCache.First(); + + while(pNode) + { + wxDCCacheEntry* pEntry = (wxDCCacheEntry*)pNode->Data(); + + // + // Don't return the same one as we already have + // + if (!pNotThis || (pNotThis != pEntry)) + { + if (pEntry->m_nDepth == nDepth) + { + return pEntry; + } + } + pNode = pNode->Next(); + } + wxDCCacheEntry* pEntry = new wxDCCacheEntry( hPS + ,nDepth + ); + AddToDCCache(pEntry); + return pEntry; +} // end of wxPMDCImpl::FindDCInCache + +void wxPMDCImpl::AddToBitmapCache( + wxDCCacheEntry* pEntry +) +{ + m_svBitmapCache.Append(pEntry); +} // end of wxPMDCImpl::AddToBitmapCache + +void wxPMDCImpl::AddToDCCache( + wxDCCacheEntry* pEntry +) +{ + m_svDCCache.Append(pEntry); +} // end of wxPMDCImpl::AddToDCCache + +void wxPMDCImpl::ClearCache() +{ + m_svBitmapCache.DeleteContents(true); + m_svBitmapCache.Clear(); + m_svBitmapCache.DeleteContents(false); + m_svDCCache.DeleteContents(true); + m_svDCCache.Clear(); + m_svDCCache.DeleteContents(false); +} // end of wxPMDCImpl::ClearCache + +// Clean up cache at app exit +class wxDCModule : public wxModule { - m_pCanvas = NULL; +public: + virtual bool OnInit() { return true; } + virtual void OnExit() { wxPMDCImpl::ClearCache(); } + +private: + DECLARE_DYNAMIC_CLASS(wxDCModule) +}; // end of CLASS wxDCModule + +IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) + +#endif // ndef for wxUSE_DC_CACHEING - m_hOldBitmap = 0; - m_hOldPen = 0; - m_hOldBrush = 0; - m_hOldFont = 0; - m_hOldPalette = 0; +// --------------------------------------------------------------------------- +// wxDC +// --------------------------------------------------------------------------- - m_bOwnsDC = FALSE; - m_hDC = 0; - m_hOldPS = NULL; - m_hPS = NULL; - m_bIsPaintTime = FALSE; // True at Paint Time - m_brush.GetColour().Set("WHITE"); -} // end of wxDC::wxDC +wxPMDCImpl::wxPMDCImpl( wxDC *owner, WXHDC hDC ) : + wxDCImpl( owner ) +{ + Init(); + m_hDC = hDC; +} // end of wxPMDCImpl::wxPMDCImpl -wxDC::~wxDC(void) +wxPMDCImpl::~wxPMDCImpl() { if ( m_hDC != 0 ) { @@ -200,12 +372,12 @@ wxDC::~wxDC(void) } } } -} // end of wxDC::~wxDC +} // end of wxPMDCImpl::~wxDC // This will select current objects out of the DC, // which is what you have to do before deleting the // DC. -void wxDC::SelectOldObjects( +void wxPMDCImpl::SelectOldObjects( WXHDC hPS ) { @@ -214,7 +386,7 @@ void wxDC::SelectOldObjects( if (m_hOldBitmap) { ::GpiSetBitmap(hPS, (HBITMAP) m_hOldBitmap); - if (m_vSelectedBitmap.Ok()) + if (m_vSelectedBitmap.IsOk()) { m_vSelectedBitmap.SetSelectedInto(NULL); } @@ -235,7 +407,7 @@ void wxDC::SelectOldObjects( m_font = wxNullFont; m_backgroundBrush = wxNullBrush; m_vSelectedBitmap = wxNullBitmap; -} // end of wxDC::SelectOldObjects +} // end of wxPMDCImpl::SelectOldObjects // --------------------------------------------------------------------------- // clipping @@ -253,7 +425,7 @@ void wxDC::SelectOldObjects( m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ } -void wxDC::DoSetClippingRegion( +void wxPMDCImpl::DoSetClippingRegion( wxCoord vX , wxCoord vY , wxCoord vWidth @@ -263,31 +435,31 @@ void wxDC::DoSetClippingRegion( RECTL vRect; vY = OS2Y(vY,vHeight); - m_clipping = TRUE; + m_clipping = true; vRect.xLeft = vX; vRect.yTop = vY + vHeight; vRect.xRight = vX + vWidth; vRect.yBottom = vY; ::GpiIntersectClipRectangle(m_hPS, &vRect); DO_SET_CLIPPING_BOX() -} // end of wxDC::DoSetClippingRegion +} // end of wxPMDCImpl::DoSetClippingRegion -void wxDC::DoSetClippingRegionAsRegion( +void wxPMDCImpl::DoSetDeviceClippingRegion( const wxRegion& rRegion ) { wxCHECK_RET(rRegion.GetHRGN(), wxT("invalid clipping region")); HRGN hRgnOld; - m_clipping = TRUE; + m_clipping = true; ::GpiSetClipRegion( m_hPS ,(HRGN)rRegion.GetHRGN() ,&hRgnOld ); DO_SET_CLIPPING_BOX() -} // end of wxDC::DoSetClippingRegionAsRegion +} // end of wxPMDCImpl::DoSetDeviceClippingRegion -void wxDC::DestroyClippingRegion(void) +void wxPMDCImpl::DestroyClippingRegion() { if (m_clipping && m_hPS) { @@ -307,61 +479,75 @@ void wxDC::DestroyClippingRegion(void) ::GpiSetClipRegion(m_hPS, hRgn, &hRgnOld); } - m_clipping = FALSE; -} // end of wxDC::DestroyClippingRegion + ResetClipping(); +} // end of wxPMDCImpl::DestroyClippingRegion // --------------------------------------------------------------------------- // query capabilities // --------------------------------------------------------------------------- -bool wxDC::CanDrawBitmap() const +bool wxPMDCImpl::CanDrawBitmap() const { - return TRUE; + return true; } -bool wxDC::CanGetTextExtent() const +bool wxPMDCImpl::CanGetTextExtent() const { LONG lTechnology = 0L; ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY, 1L, &lTechnology); return (lTechnology == CAPS_TECH_RASTER_DISPLAY) || (lTechnology == CAPS_TECH_RASTER_PRINTER); -} // end of wxDC::CanGetTextExtent +} // end of wxPMDCImpl::CanGetTextExtent -int wxDC::GetDepth() const +int wxPMDCImpl::GetDepth() const { - LONG lArray[CAPS_COLOR_BITCOUNT]; - int nBitsPerPixel; + LONG lCapsColorBitcount; + int nBitsPerPixel = 0; if(::DevQueryCaps( GetHDC() - ,CAPS_FAMILY ,CAPS_COLOR_BITCOUNT - ,lArray + ,1L + ,&lCapsColorBitcount )) { - nBitsPerPixel = (int)lArray[CAPS_COLOR_BITCOUNT]; + nBitsPerPixel = (int)lCapsColorBitcount; } return nBitsPerPixel; -} // end of wxDC::GetDepth +} // end of wxPMDCImpl::GetDepth // --------------------------------------------------------------------------- // drawing // --------------------------------------------------------------------------- -void wxDC::Clear() +void wxPMDCImpl::Clear() { + // + // If this is a canvas DC then just fill with the background color + // Otherwise purge the whole thing + // + if (m_pCanvas) + { + RECTL vRect; + + ::GpiQueryClipBox(m_hPS, &vRect); + ::WinFillRect(m_hPS, &vRect, ::GpiQueryBackColor(m_hPS)); + } + else ::GpiErase(m_hPS); -} // end of wxDC::Clear +} // end of wxPMDCImpl::Clear -void wxDC::DoFloodFill( +bool wxPMDCImpl::DoFloodFill( wxCoord vX , wxCoord vY , const wxColour& rCol -, int nStyle +, wxFloodFillStyle nStyle ) { POINTL vPtlPos; LONG lColor; LONG lOptions; + LONG lHits; + bool bSuccess = false; vPtlPos.x = vX; // Loads x-coordinate vPtlPos.y = OS2Y(vY,0); // Loads y-coordinate @@ -371,10 +557,13 @@ void wxDC::DoFloodFill( if(wxFLOOD_SURFACE == nStyle) lOptions = FF_SURFACE; - ::GpiFloodFill(m_hPS, lOptions, lColor); -} // end of wxDC::DoFloodFill + if ((lHits = ::GpiFloodFill(m_hPS, lOptions, lColor)) != GPI_ERROR) + bSuccess = true; -bool wxDC::DoGetPixel( + return bSuccess; +} // end of wxPMDCImpl::DoFloodFill + +bool wxPMDCImpl::DoGetPixel( wxCoord vX , wxCoord vY , wxColour* pCol @@ -385,17 +574,7 @@ bool wxDC::DoGetPixel( vPoint.x = vX; vPoint.y = OS2Y(vY,0); - lColor = ::GpiSetPel(m_hPS, &vPoint); - - // - // Get the color of the pen - // - LONG lPencolor = 0x00ffffff; - - if (m_pen.Ok()) - { - lPencolor = m_pen.GetColour().GetPixel(); - } + lColor = ::GpiQueryPel(m_hPS, &vPoint); // // return the color of the pixel @@ -405,10 +584,10 @@ bool wxDC::DoGetPixel( ,GetGValue(lColor) ,GetBValue(lColor) ); - return(lColor == lPencolor); -} // end of wxDC::DoGetPixel + return true; +} // end of wxPMDCImpl::DoGetPixel -void wxDC::DoCrossHair( +void wxPMDCImpl::DoCrossHair( wxCoord vX , wxCoord vY ) @@ -440,9 +619,9 @@ void wxDC::DoCrossHair( ::GpiLine(m_hPS, &vPoint[3]); CalcBoundingBox(vX1, vY1); CalcBoundingBox(vX2, vY2); -} // end of wxDC::DoCrossHair +} // end of wxPMDCImpl::DoCrossHair -void wxDC::DoDrawLine( +void wxPMDCImpl::DoDrawLine( wxCoord vX1 , wxCoord vY1 , wxCoord vX2 @@ -450,19 +629,43 @@ void wxDC::DoDrawLine( ) { POINTL vPoint[2]; + COLORREF vColor = 0x00ffffff; - vY1 = OS2Y(vY1,0); - vY2 = OS2Y(vY2,0); - + // + // Might be a memory DC with no Paint rect. + // + if (!(m_vRclPaint.yTop == 0 && + m_vRclPaint.yBottom == 0 && + m_vRclPaint.xRight == 0 && + m_vRclPaint.xLeft == 0)) + { + vY1 = OS2Y(vY1,0); + vY2 = OS2Y(vY2,0); + } + else + { + if (m_vSelectedBitmap.IsOk()) + { + m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); + m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); + vY1 = OS2Y(vY1,0); + vY2 = OS2Y(vY2,0); + } + } vPoint[0].x = vX1; vPoint[0].y = vY1; vPoint[1].x = vX2; vPoint[1].y = vY2; + if (m_pen.IsOk()) + { + vColor = m_pen.GetColour().GetPixel(); + } + ::GpiSetColor(m_hPS, vColor); ::GpiMove(m_hPS, &vPoint[0]); ::GpiLine(m_hPS, &vPoint[1]); CalcBoundingBox(vX1, vY1); CalcBoundingBox(vX2, vY2); -} // end of wxDC::DoDrawLine +} // end of wxPMDCImpl::DoDrawLine ////////////////////////////////////////////////////////////////////////////// // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) @@ -470,7 +673,7 @@ void wxDC::DoDrawLine( // current brush for filling the shape. The arc is drawn in an anticlockwise // direction from the start point to the end point. ////////////////////////////////////////////////////////////////////////////// -void wxDC::DoDrawArc( +void wxPMDCImpl::DoDrawArc( wxCoord vX1 , wxCoord vY1 , wxCoord vX2 @@ -481,8 +684,6 @@ void wxDC::DoDrawArc( { POINTL vPtlPos; POINTL vPtlArc[2]; // Structure for current position - int nDx; - int nDy; double dRadius; double dAngl1; double dAngl2; @@ -519,8 +720,8 @@ void wxDC::DoDrawArc( // Medium point // dAnglmid = (dAngl1 + dAngl2)/2. + M_PI; - vXm = vXc + dRadius * cos(dAnglmid); - vYm = vYc + dRadius * sin(dAnglmid); + vXm = (wxCoord)(vXc + dRadius * cos(dAnglmid)); + vYm = (wxCoord)(vYc + dRadius * sin(dAnglmid)); DoDrawArc( vX1, vY1 ,vXm, vYm ,vXc, vYc @@ -536,8 +737,8 @@ void wxDC::DoDrawArc( // Medium point // dAnglmid = (dAngl1 + dAngl2)/2.; - vXm = vXc + dRadius * cos(dAnglmid); - vYm = vYc + dRadius * sin(dAnglmid); + vXm = (wxCoord)(vXc + dRadius * cos(dAnglmid)); + vYm = (wxCoord)(vYc + dRadius * sin(dAnglmid)); // // Ellipse main axis (r,q), (p,s) with center at (0,0) */ @@ -556,15 +757,15 @@ void wxDC::DoDrawArc( vPtlArc[1].x = vX2; vPtlArc[1].y = vY2; ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc - CalcBoundingBox( (vXc - dRadius) - ,(vYc - dRadius) + CalcBoundingBox( (wxCoord)(vXc - dRadius) + ,(wxCoord)(vYc - dRadius) ); - CalcBoundingBox( (vXc + dRadius) - ,(vYc + dRadius) + CalcBoundingBox( (wxCoord)(vXc + dRadius) + ,(wxCoord)(vYc + dRadius) ); -} // end of wxDC::DoDrawArc +} // end of wxPMDCImpl::DoDrawArc -void wxDC::DoDrawCheckMark( +void wxPMDCImpl::DoDrawCheckMark( wxCoord vX1 , wxCoord vY1 , wxCoord vWidth @@ -611,9 +812,9 @@ void wxDC::DoDrawCheckMark( CalcBoundingBox( vX2 ,vY2 ); -} // end of wxDC::DoDrawCheckMark +} // end of wxPMDCImpl::DoDrawCheckMark -void wxDC::DoDrawPoint( +void wxPMDCImpl::DoDrawPoint( wxCoord vX , wxCoord vY ) @@ -621,7 +822,7 @@ void wxDC::DoDrawPoint( POINTL vPoint; COLORREF vColor = 0x00ffffff; - if (m_pen.Ok()) + if (m_pen.IsOk()) { vColor = m_pen.GetColour().GetPixel(); } @@ -632,49 +833,46 @@ void wxDC::DoDrawPoint( CalcBoundingBox( vX ,vY ); -} // end of wxDC::DoDrawPoint +} // end of wxPMDCImpl::DoDrawPoint -void wxDC::DoDrawPolygon( - int n -, wxPoint vPoints[] -, wxCoord vXoffset -, wxCoord vYoffset -, int nFillStyle -) +void wxPMDCImpl::DoDrawPolygon( int n, + wxPoint vPoints[], + wxCoord vXoffset, + wxCoord vYoffset, + wxPolygonFillMode nFillStyle ) { - ULONG ulCount = 1; // Number of polygons. - POLYGON vPlgn; // polygon. - ULONG flOptions = 0L; // Drawing options. - -////////////////////////////////////////////////////////////////////////////// -// This contains fields of option bits... to draw boundary lines as well as -// the area interior. -// -// Drawing boundary lines: -// POLYGON_NOBOUNDARY Does not draw boundary lines. -// POLYGON_BOUNDARY Draws boundary lines (the default). -// -// Construction of the area interior: -// POLYGON_ALTERNATE Constructs interior in alternate mode -// (the default). -// POLYGON_WINDING Constructs interior in winding mode. -////////////////////////////////////////////////////////////////////////////// - - ULONG flModel = 0L; // Drawing model. - -////////////////////////////////////////////////////////////////////////////// -// Drawing model. -// POLYGON_INCL Fill is inclusive of bottom right (the default). -// POLYGON_EXCL Fill is exclusive of bottom right. -// This is provided to aid migration from other graphics models. -////////////////////////////////////////////////////////////////////////////// + ULONG ulCount = 1; // Number of polygons. + POLYGON vPlgn; // polygon. + ULONG flOptions = 0L; // Drawing options. - LONG lHits = 0L; // Correlation/error indicator. - POINTL vPoint; - int i; - int nIsTRANSPARENT = 0; - LONG lBorderColor = 0L; - LONG lColor = 0L; + ////////////////////////////////////////////////////////////////////////////// + // This contains fields of option bits... to draw boundary lines as well as + // the area interior. + // + // Drawing boundary lines: + // POLYGON_NOBOUNDARY Does not draw boundary lines. + // POLYGON_BOUNDARY Draws boundary lines (the default). + // + // Construction of the area interior: + // POLYGON_ALTERNATE Constructs interior in alternate mode + // (the default). + // POLYGON_WINDING Constructs interior in winding mode. + ////////////////////////////////////////////////////////////////////////////// + + ULONG flModel = POLYGON_INCL; // Drawing model. + + ////////////////////////////////////////////////////////////////////////////// + // Drawing model. + // POLYGON_INCL Fill is inclusive of bottom right (the default). + // POLYGON_EXCL Fill is exclusive of bottom right. + // This is provided to aid migration from other graphics models. + ////////////////////////////////////////////////////////////////////////////// + + LONG lHits = 0L; // Correlation/error indicator. + int i; + int nIsTRANSPARENT = 0; + LONG lBorderColor = 0L; + LONG lColor = 0L; lBorderColor = m_pen.GetColour().GetPixel(); lColor = m_brush.GetColour().GetPixel(); @@ -688,25 +886,22 @@ void wxDC::DoDrawPolygon( for(i = 0; i < n; i++) { - vPlgn.aPointl[i].x = vPoints[i].x; // +xoffset; - vPlgn.aPointl[i].y = OS2Y(vPoints[i].y,0); // +yoffset; + vPlgn.aPointl[i].x = vPoints[i].x+vXoffset; + vPlgn.aPointl[i].y = OS2Y(vPoints[i].y+vYoffset,0); } - flModel = POLYGON_BOUNDARY; + flOptions = POLYGON_BOUNDARY; if(nFillStyle == wxWINDING_RULE) - flModel |= POLYGON_WINDING; + flOptions |= POLYGON_WINDING; else - flModel |= POLYGON_ALTERNATE; - - vPoint.x = vXoffset; - vPoint.y = OS2Y(vYoffset,0); + flOptions |= POLYGON_ALTERNATE; ::GpiSetColor(m_hPS, lBorderColor); - ::GpiMove(m_hPS, &vPoint); + ::GpiMove(m_hPS, &vPlgn.aPointl[0]); lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel); free(vPlgn.aPointl); -} // end of wxDC::DoDrawPolygon +} // end of wxPMDCImpl::DoDrawPolygon -void wxDC::DoDrawLines( +void wxPMDCImpl::DoDrawLines( int n , wxPoint vPoints[] , wxCoord vXoffset @@ -715,7 +910,7 @@ void wxDC::DoDrawLines( { POINTL vPoint; - if (vXoffset != 0L || vXoffset != 0L) + if (vXoffset != 0L || vYoffset != 0L) { int i; @@ -737,8 +932,8 @@ void wxDC::DoDrawLines( { int i; - CalcBoundingBox( vPoints[i].x - ,vPoints[i].y + CalcBoundingBox( vPoints[0].x + ,vPoints[0].y ); vPoint.x = vPoints[0].x; vPoint.y = OS2Y(vPoints[0].y,0); @@ -754,9 +949,9 @@ void wxDC::DoDrawLines( ::GpiLine(m_hPS, &vPoint); } } -} // end of wxDC::DoDrawLines +} // end of wxPMDCImpl::DoDrawLines -void wxDC::DoDrawRectangle( +void wxPMDCImpl::DoDrawRectangle( wxCoord vX , wxCoord vY , wxCoord vWidth @@ -769,15 +964,31 @@ void wxDC::DoDrawRectangle( LONG lBorderColor; int nIsTRANSPARENT = 0; - vY = OS2Y(vY,vHeight); + // + // Might be a memory DC with no Paint rect. + // + if (!(m_vRclPaint.yTop == 0 && + m_vRclPaint.yBottom == 0 && + m_vRclPaint.xRight == 0 && + m_vRclPaint.xLeft == 0)) + vY = OS2Y(vY,vHeight); + else + { + if (m_vSelectedBitmap.IsOk()) + { + m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); + m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); + vY = OS2Y(vY,vHeight); + } + } wxCoord vX2 = vX + vWidth; wxCoord vY2 = vY + vHeight; vPoint[0].x = vX; vPoint[0].y = vY; - vPoint[1].x = vX + vWidth; - vPoint[1].y = vY + vHeight; + vPoint[1].x = vX + vWidth - 1; + vPoint[1].y = vY + vHeight - 1; ::GpiMove(m_hPS, &vPoint[0]); lColor = m_brush.GetColour().GetPixel(); lBorderColor = m_pen.GetColour().GetPixel(); @@ -789,7 +1000,7 @@ void wxDC::DoDrawRectangle( if(m_brush.GetStyle() == wxTRANSPARENT) lControl = DRO_OUTLINE; - ::GpiSetColor(m_hPS, lColor); + ::GpiSetColor(m_hPS, lBorderColor); ::GpiBox( m_hPS // handle to a presentation space ,lControl // draw the box outline ? or ? ,&vPoint[1] // address of the corner @@ -816,7 +1027,7 @@ void wxDC::DoDrawRectangle( vPoint[0].x = vX + 1; vPoint[0].y = vY + 1; vPoint[1].x = vX + vWidth - 2; - vPoint[1].y = vY + vHeight + 2; + vPoint[1].y = vY + vHeight - 2; ::GpiMove(m_hPS, &vPoint[0]); ::GpiBox( m_hPS ,lControl @@ -827,9 +1038,9 @@ void wxDC::DoDrawRectangle( } CalcBoundingBox(vX, vY); CalcBoundingBox(vX2, vY2); -} // end of wxDC::DoDrawRectangle +} // end of wxPMDCImpl::DoDrawRectangle -void wxDC::DoDrawRoundedRectangle( +void wxPMDCImpl::DoDrawRoundedRectangle( wxCoord vX , wxCoord vY , wxCoord vWidth @@ -839,33 +1050,91 @@ void wxDC::DoDrawRoundedRectangle( { POINTL vPoint[2]; LONG lControl; + LONG lColor; + LONG lBorderColor; + int nIsTRANSPARENT = 0; - vY = OS2Y(vY,vHeight); + // + // Might be a memory DC with no Paint rect. + // + if (!(m_vRclPaint.yTop == 0 && + m_vRclPaint.yBottom == 0 && + m_vRclPaint.xRight == 0 && + m_vRclPaint.xLeft == 0)) + vY = OS2Y(vY,vHeight); + else + { + if (m_vSelectedBitmap.IsOk()) + { + m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); + m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); + vY = OS2Y(vY,vHeight); + } + } wxCoord vX2 = (vX + vWidth); wxCoord vY2 = (vY + vHeight); vPoint[0].x = vX; - vPoint[0].y = YLOG2DEV(vY) - vHeight; - vPoint[1].x = vX + vWidth; - vPoint[1].y = vY; + vPoint[0].y = vY; + vPoint[1].x = vX + vWidth - 1; + vPoint[1].y = vY + vHeight - 1; ::GpiMove(m_hPS, &vPoint[0]); + lColor = m_brush.GetColour().GetPixel(); + lBorderColor = m_pen.GetColour().GetPixel(); lControl = DRO_OUTLINEFILL; //DRO_FILL; if (m_brush.GetStyle() == wxTRANSPARENT) + nIsTRANSPARENT = 1; + if(lColor == lBorderColor || nIsTRANSPARENT) + { + lControl = DRO_OUTLINEFILL; //DRO_FILL; + if(m_brush.GetStyle() == wxTRANSPARENT) + lControl = DRO_OUTLINE; + + ::GpiSetColor(m_hPS, lColor); + ::GpiBox( m_hPS // handle to a presentation space + ,lControl // draw the box outline ? or ? + ,&vPoint[1] // address of the corner + ,(LONG)dRadius // horizontal corner radius + ,(LONG)dRadius // vertical corner radius + ); + } + else + { lControl = DRO_OUTLINE; - ::GpiBox( m_hPS // handle to a presentation space - ,DRO_OUTLINE // draw the box outline ? or ? - ,&vPoint[1] // address of the corner - ,(LONG)dRadius // horizontal corner radius - ,(LONG)dRadius // vertical corner radius - ); + ::GpiSetColor( m_hPS + ,lBorderColor + ); + ::GpiBox( m_hPS + ,lControl + ,&vPoint[1] + ,(LONG)dRadius + ,(LONG)dRadius + ); + lControl = DRO_FILL; + ::GpiSetColor( m_hPS + ,lColor + ); + vPoint[0].x = vX + 1; + vPoint[0].y = vY + 1; + vPoint[1].x = vX + vWidth - 2; + vPoint[1].y = vY + vHeight - 2; + ::GpiMove(m_hPS, &vPoint[0]); + ::GpiBox( m_hPS + ,lControl + ,&vPoint[1] + ,(LONG)dRadius + ,(LONG)dRadius + ); + } + CalcBoundingBox(vX, vY); CalcBoundingBox(vX2, vY2); -} // end of wxDC::DoDrawRoundedRectangle +} // end of wxPMDCImpl::DoDrawRoundedRectangle // Draw Ellipse within box (x,y) - (x+width, y+height) -void wxDC::DoDrawEllipse( +void wxPMDCImpl::DoDrawEllipse( wxCoord vX , wxCoord vY , wxCoord vWidth @@ -905,9 +1174,9 @@ void wxDC::DoDrawEllipse( CalcBoundingBox(vX, vY); CalcBoundingBox(vX2, vY2); -} // end of wxDC::DoDrawEllipse +} // end of wxPMDCImpl::DoDrawEllipse -void wxDC::DoDrawEllipticArc( +void wxPMDCImpl::DoDrawEllipticArc( wxCoord vX , wxCoord vY , wxCoord vWidth @@ -923,7 +1192,6 @@ void wxDC::DoDrawEllipticArc( FIXED vFSweepa; // Start angle, sweep angle double dIntPart; double dFractPart; - double dRadius; vY = OS2Y(vY,vHeight); @@ -940,8 +1208,8 @@ void wxDC::DoDrawEllipticArc( vArcp.lP = vWidth/2; vArcp.lS = 0; ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default - vPtlPos.x = vX + vWidth/2 * (1. + cos(DegToRad(dSa))); // Loads x-coordinate - vPtlPos.y = vY + vHeight/2 * (1. + sin(DegToRad(dSa))); // Loads y-coordinate + vPtlPos.x = (wxCoord)(vX + vWidth/2 * (1. + cos(DegToRad(dSa)))); // Loads x-coordinate + vPtlPos.y = (wxCoord)(vY + vHeight/2 * (1. + sin(DegToRad(dSa)))); // Loads y-coordinate ::GpiMove(m_hPS, &vPtlPos); // Sets current position // @@ -965,47 +1233,441 @@ void wxDC::DoDrawEllipticArc( CalcBoundingBox(vX, vY); CalcBoundingBox(vX2, vY2); -} // end of wxDC::DoDrawEllipticArc +} // end of wxPMDCImpl::DoDrawEllipticArc -void wxDC::DoDrawIcon( +void wxPMDCImpl::DoDrawIcon( const wxIcon& rIcon , wxCoord vX , wxCoord vY ) { - vY = OS2Y(vY,rIcon.GetHeight()); - wxCHECK_RET( rIcon.Ok(), wxT("invalid icon in DrawIcon") ); + // + // Need to copy back into a bitmap. ::WinDrawPointer uses device coords + // and I don't feel like figuring those out for scrollable windows so + // just convert to a bitmap then let the DoDrawBitmap routine display it + // + if (rIcon.IsXpm()) + { + DoDrawBitmap(rIcon.GetXpmSrc(), vX, vY, true); + } + else + { + wxBitmap vBitmap(rIcon); - ::WinDrawPointer( GetHPS() - ,vX - ,vY - ,(HPOINTER)GetHiconOf(rIcon) - ,DP_NORMAL - ); + DoDrawBitmap(vBitmap, vX, vY, false); + } CalcBoundingBox(vX, vY); CalcBoundingBox(vX + rIcon.GetWidth(), vY + rIcon.GetHeight()); -} // end of wxDC::DoDrawIcon +} // end of wxPMDCImpl::DoDrawIcon -void wxDC::DoDrawBitmap( +void wxPMDCImpl::DoDrawBitmap( const wxBitmap& rBmp , wxCoord vX , wxCoord vY , bool bUseMask ) { - POINTL vPoint = {vX, vY}; +#if wxUSE_PRINTING_ARCHITECTURE + if (!IsKindOf(CLASSINFO(wxPrinterDC))) +#endif + { + HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP(); + HBITMAP hBitmapOld = NULLHANDLE; + POINTL vPoint[4]; + + vY = OS2Y(vY,rBmp.GetHeight()); + + vPoint[0].x = vX; + vPoint[0].y = vY + rBmp.GetHeight(); + vPoint[1].x = vX + rBmp.GetWidth(); + vPoint[1].y = vY; + vPoint[2].x = 0; + vPoint[2].y = 0; + vPoint[3].x = rBmp.GetWidth(); + vPoint[3].y = rBmp.GetHeight(); + if (bUseMask) + { + wxMask* pMask = rBmp.GetMask(); - ::WinDrawBitmap( GetHPS() - ,(HBITMAP)GetHbitmapOf(rBmp) - ,NULL - ,&vPoint - ,0L - ,0L - ,DBM_NORMAL - ); -} // end of wxDC::DoDrawBitmap + if (pMask) + { + // + // Need to imitate ::MaskBlt in windows. + // 1) Extract the bits from from the bitmap. + // 2) Extract the bits from the mask + // 3) Using the mask bits do the following: + // A) If the mask byte is 00 leave the bitmap byte alone + // B) If the mask byte is FF copy the screen color into + // bitmap byte + // 4) Create a new bitmap and set its bits to the above result + // 5) Blit this to the screen PS + // + HBITMAP hMask = (HBITMAP)pMask->GetMaskBitmap(); + HBITMAP hOldMask = NULLHANDLE; + HBITMAP hOldBitmap = NULLHANDLE; + HBITMAP hNewBitmap = NULLHANDLE; + unsigned char* pucBits; // buffer that will contain the bitmap data + unsigned char* pucBitsMask; // buffer that will contain the mask data + unsigned char* pucData; // pointer to use to traverse bitmap data + unsigned char* pucDataMask; // pointer to use to traverse mask data + LONG lHits; + ERRORID vError; + wxString sError; -void wxDC::DoDrawText( + // + // The usual Memory context creation stuff + // + DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; + SIZEL vSize = {0, 0}; + HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE); + HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC); + + // + // The usual bitmap header stuff + // + BITMAPINFOHEADER2 vHeader; + BITMAPINFO2 vInfo; + + memset(&vHeader, '\0', 16); + vHeader.cbFix = 16; + + memset(&vInfo, '\0', 16); + vInfo.cbFix = 16; + vInfo.cx = (ULONG)rBmp.GetWidth(); + vInfo.cy = (ULONG)rBmp.GetHeight(); + vInfo.cPlanes = 1; + vInfo.cBitCount = 24; // Set to desired count going in + + // + // Create the buffers for data....all wxBitmaps are 24 bit internally + // + int nBytesPerLine = rBmp.GetWidth() * 3; + int nSizeDWORD = sizeof(DWORD); + int nLineBoundary = nBytesPerLine % nSizeDWORD; + int nPadding = 0; + int i; + int j; + LONG lScans = 0L; + LONG lColor = 0L; + + // + // Need to get a background color for mask blitting + // + if (IsKindOf(CLASSINFO(wxWindowDCImpl))) + { + wxWindowDCImpl* pWindowDC = wxDynamicCast(this, wxWindowDCImpl); + + lColor = pWindowDC->m_pCanvas->GetBackgroundColour().GetPixel(); + } + else if (GetBrush().IsOk()) + lColor = GetBrush().GetColour().GetPixel(); + else + lColor = m_textBackgroundColour.GetPixel(); + + // + // Bitmap must be in a double-word aligned address so we may + // have some padding to worry about + // + if (nLineBoundary > 0) + { + nPadding = nSizeDWORD - nLineBoundary; + nBytesPerLine += nPadding; + } + pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); + pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); + memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight())); + memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight())); + + // + // Extract the bitmap and mask data + // + if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + } + ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader); + vInfo.cBitCount = 24; + if ((lScans = ::GpiQueryBitmapBits( hPS + ,0L + ,(LONG)rBmp.GetHeight() + ,(PBYTE)pucBits + ,&vInfo + )) == GPI_ALTERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + } + if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + } + ::GpiQueryBitmapInfoHeader(hMask, &vHeader); + vInfo.cBitCount = 24; + if ((lScans = ::GpiQueryBitmapBits( hPS + ,0L + ,(LONG)rBmp.GetHeight() + ,(PBYTE)pucBitsMask + ,&vInfo + )) == GPI_ALTERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + } + if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + } + + // + // Now set the bytes(bits) according to the mask values + // 3 bytes per pel...must handle one at a time + // + pucData = pucBits; + pucDataMask = pucBitsMask; + + // + // 16 bit kludge really only kinda works. The mask gets applied + // where needed but the original bitmap bits are dorked sometimes + // + bool bpp16 = (wxDisplayDepth() == 16); + + for (i = 0; i < rBmp.GetHeight(); i++) + { + for (j = 0; j < rBmp.GetWidth(); j++) + { + // Byte 1 + if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook + pucData++; + else if (*pucDataMask == 0xFF) // leave bitmap byte alone + pucData++; + else + { + *pucData = ((unsigned char)(lColor >> 16)); + pucData++; + } + // Byte 2 + if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook + pucData++; + else if (*(pucDataMask + 1) == 0xFF) // leave bitmap byte alone + pucData++; + else + { + *pucData = ((unsigned char)(lColor >> 8)); + pucData++; + } + + // Byte 3 + if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook + pucData++; + else if (*(pucDataMask + 2) == 0xFF) // leave bitmap byte alone + pucData++; + else + { + *pucData = ((unsigned char)lColor); + pucData++; + } + pucDataMask += 3; + } + for (j = 0; j < nPadding; j++) + { + pucData++; + pucDataMask++; + } + } + // + // Create a new bitmap + // + vHeader.cx = (ULONG)rBmp.GetWidth(); + vHeader.cy = (ULONG)rBmp.GetHeight(); + vHeader.cPlanes = 1L; + vHeader.cBitCount = 24; + if ((hNewBitmap = ::GpiCreateBitmap( hPS + ,&vHeader + ,CBM_INIT + ,(PBYTE)pucBits + ,&vInfo + )) == GPI_ERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + } + + // + // Now blit it to the screen PS + // + if ((lHits = ::GpiWCBitBlt( (HPS)GetHPS() + ,hNewBitmap + ,4 + ,vPoint + ,ROP_SRCCOPY + ,BBO_IGNORE + )) == GPI_ERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + } + + // + // Clean up + // + free(pucBits); + free(pucBitsMask); + ::GpiSetBitmap(hPS, NULLHANDLE); + ::GpiDeleteBitmap(hNewBitmap); + ::GpiDestroyPS(hPS); + ::DevCloseDC(hDC); + } + } + else + { + ULONG lOldForeGround = ::GpiQueryColor((HPS)GetHPS()); + ULONG lOldBackGround = ::GpiQueryBackColor((HPS)GetHPS()); + + if (m_textForegroundColour.IsOk()) + { + ::GpiSetColor( (HPS)GetHPS() + ,m_textForegroundColour.GetPixel() + ); + } + if (m_textBackgroundColour.IsOk()) + { + ::GpiSetBackColor( (HPS)GetHPS() + ,m_textBackgroundColour.GetPixel() + ); + } + // + // Need to alter bits in a mono bitmap to match the new + // background-foreground if it is different. + // + if (rBmp.IsMono() && + ((m_textForegroundColour.GetPixel() != lOldForeGround) || + (m_textBackgroundColour.GetPixel() != lOldBackGround))) + { + DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; + SIZEL vSize = {0, 0}; + HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE); + HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC); + + int nBytesPerLine = rBmp.GetWidth() * 3; + int i, j; + LONG lForeGround = m_textForegroundColour.GetPixel(); + LONG lBackGround = m_textBackgroundColour.GetPixel(); + LONG lScans; + HBITMAP hOldBitmap = NULLHANDLE; + BITMAPINFO2 vInfo; + ERRORID vError; + wxString sError; + + + memset(&vInfo, '\0', 16); + vInfo.cbFix = 16; + vInfo.cx = (ULONG)rBmp.GetWidth(); + vInfo.cy = (ULONG)rBmp.GetHeight(); + vInfo.cPlanes = 1; + vInfo.cBitCount = 24; + + unsigned char* pucBits; // buffer that will contain the bitmap data + unsigned char* pucData; // pointer to use to traverse bitmap data + + pucBits = new unsigned char[nBytesPerLine * rBmp.GetHeight()]; + memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight())); + + if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + delete [] pucBits; + return; + } + if ((lScans = ::GpiQueryBitmapBits( hPS + ,0L + ,(LONG)rBmp.GetHeight() + ,(PBYTE)pucBits + ,&vInfo + )) == GPI_ALTERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + delete [] pucBits; + return; + } + unsigned char cOldRedFore = (unsigned char)(lOldForeGround >> 16); + unsigned char cOldGreenFore = (unsigned char)(lOldForeGround >> 8); + unsigned char cOldBlueFore = (unsigned char)lOldForeGround; + + unsigned char cRedFore = (unsigned char)(lForeGround >> 16); + unsigned char cGreenFore = (unsigned char)(lForeGround >> 8); + unsigned char cBlueFore = (unsigned char)lForeGround; + + unsigned char cRedBack = (unsigned char)(lBackGround >> 16); + unsigned char cGreenBack = (unsigned char)(lBackGround >> 8); + unsigned char cBlueBack = (unsigned char)lBackGround; + + pucData = pucBits; + for (i = 0; i < rBmp.GetHeight(); i++) + { + for (j = 0; j < rBmp.GetWidth(); j++) + { + unsigned char cBmpRed = *pucData; + unsigned char cBmpGreen = *(pucData + 1); + unsigned char cBmpBlue = *(pucData + 2); + + if ((cBmpRed == cOldRedFore) && + (cBmpGreen == cOldGreenFore) && + (cBmpBlue == cOldBlueFore)) + { + *pucData = cBlueFore; + pucData++; + *pucData = cGreenFore; + pucData++; + *pucData = cRedFore; + pucData++; + } + else + { + *pucData = cBlueBack; + pucData++; + *pucData = cGreenBack; + pucData++; + *pucData = cRedBack; + pucData++; + } + } + } + if ((lScans = ::GpiSetBitmapBits( hPS + ,0L + ,(LONG)rBmp.GetHeight() + ,(PBYTE)pucBits + ,&vInfo + )) == GPI_ALTERROR) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + return; + } + delete [] pucBits; + ::GpiSetBitmap(hPS, NULLHANDLE); + ::GpiDestroyPS(hPS); + ::DevCloseDC(hDC); + } + ::GpiWCBitBlt( (HPS)GetHPS() + ,hBitmap + ,4 + ,vPoint + ,ROP_SRCCOPY + ,BBO_IGNORE + ); + ::GpiSetBitmap((HPS)GetHPS(), hBitmapOld); + ::GpiSetColor((HPS)GetHPS(), lOldForeGround); + ::GpiSetBackColor((HPS)GetHPS(), lOldBackGround); + } + } +} // end of wxPMDCImpl::DoDrawBitmap + +void wxPMDCImpl::DoDrawText( const wxString& rsText , wxCoord vX , wxCoord vY @@ -1020,15 +1682,13 @@ void wxDC::DoDrawText( ); CalcBoundingBox(vX, vY); - GetTextExtent(rsText, &vWidth, &vHeight); + GetOwner()->GetTextExtent(rsText, &vWidth, &vHeight); CalcBoundingBox((vX + vWidth), (vY + vHeight)); -} // end of wxDC::DoDrawText +} // end of wxPMDCImpl::DoDrawText -void wxDC::DrawAnyText( - const wxString& rsText -, wxCoord vX -, wxCoord vY -) +void wxPMDCImpl::DrawAnyText( const wxString& rsText, + wxCoord vX, + wxCoord vY ) { int nOldBackground = 0; POINTL vPtlStart; @@ -1043,14 +1703,14 @@ void wxDC::DrawAnyText( // // Set text color attributes // - if (m_textForegroundColour.Ok()) + if (m_textForegroundColour.IsOk()) { SetTextColor( m_hPS ,(int)m_textForegroundColour.GetPixel() ); } - if (m_textBackgroundColour.Ok()) + if (m_textBackgroundColour.IsOk()) { nOldBackground = SetTextBkColor( m_hPS ,(int)m_textBackgroundColour.GetPixel() @@ -1059,18 +1719,35 @@ void wxDC::DrawAnyText( SetBkMode( m_hPS ,m_backgroundMode ); - GetTextExtent( rsText - ,&vTextX - ,&vTextY - ); + GetOwner()->GetTextExtent( rsText + ,&vTextX + ,&vTextY + ); vPtlStart.x = vX; - vPtlStart.y = OS2Y(vY,vTextY); + if (!(m_vRclPaint.yTop == 0 && + m_vRclPaint.yBottom == 0 && + m_vRclPaint.xRight == 0 && + m_vRclPaint.xLeft == 0)) + { + vPtlStart.y = OS2Y(vY,vTextY); + } + else + { + if (m_vSelectedBitmap.IsOk()) + { + m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight(); + m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth(); + vPtlStart.y = OS2Y(vY,vTextY); + } + else + vPtlStart.y = vY; + } - lHits = ::GpiCharStringAt( m_hPS - ,&vPtlStart - ,rsText.length() - ,(PCH)rsText.c_str() - ); + ::GpiMove(m_hPS, &vPtlStart); + lHits = ::GpiCharString( m_hPS + ,rsText.length() + ,rsText.char_str() + ); if (lHits != GPI_OK) { wxLogLastError(wxT("TextOut")); @@ -1081,7 +1758,7 @@ void wxDC::DrawAnyText( // it never is set to anything else, but background should remain // transparent even if we just drew an opaque string) // - if (m_textBackgroundColour.Ok()) + if (m_textBackgroundColour.IsOk()) SetTextBkColor( m_hPS ,nOldBackground ); @@ -1090,7 +1767,7 @@ void wxDC::DrawAnyText( ); } -void wxDC::DoDrawRotatedText( +void wxPMDCImpl::DoDrawRotatedText( const wxString& rsText , wxCoord vX , wxCoord vY @@ -1161,7 +1838,51 @@ void wxDC::DoDrawRotatedText( // set GDI objects // --------------------------------------------------------------------------- -void wxDC::SetPalette( +void wxPMDCImpl::DoSelectPalette( bool WXUNUSED(bRealize) ) +{ + // + // Set the old object temporarily, in case the assignment deletes an object + // that's not yet selected out. + // + if (m_hOldPalette) + { + m_hOldPalette = 0; + } + + if (m_palette.IsOk()) + { + HPALETTE hOldPal; + + hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE()); + if (!m_hOldPalette) + m_hOldPalette = (WXHPALETTE)hOldPal; + } +} // end of wxPMDCImpl::DoSelectPalette + +void wxPMDCImpl::InitializePalette() +{ + if (wxDisplayDepth() <= 8 ) + { + // + // Look for any window or parent that has a custom palette. If any has + // one then we need to use it in drawing operations + // + wxWindow* pWin = m_pCanvas->GetAncestorWithCustomPalette(); + + m_hasCustomPalette = pWin && pWin->HasCustomPalette(); + if (m_hasCustomPalette) + { + m_palette = pWin->GetPalette(); + + // + // turn on PM translation for this palette + // + DoSelectPalette(); + } + } +} // end of wxPMDCImpl::InitializePalette + +void wxPMDCImpl::SetPalette( const wxPalette& rPalette ) { @@ -1170,7 +1891,7 @@ void wxDC::SetPalette( m_hOldFont = 0; } m_palette = rPalette; - if (!rPalette.Ok()) + if (!rPalette.IsOk()) { if (m_hOldFont) { @@ -1180,9 +1901,9 @@ void wxDC::SetPalette( HPALETTE hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE()); if (!m_hOldPalette) m_hOldPalette = (WXHPALETTE)hOldPal; -} // end of wxDC::SetPalette +} // end of wxPMDCImpl::SetPalette -void wxDC::SetFont( +void wxPMDCImpl::SetFont( const wxFont& rFont ) { @@ -1195,42 +1916,40 @@ void wxDC::SetFont( m_hOldFont = 0; } m_font = rFont; - if (!rFont.Ok()) + if (!rFont.IsOk()) { m_hOldFont = 0; } m_font.SetPS(m_hPS); // this will realize the font - if (m_font.Ok()) + if (m_font.IsOk()) { HFONT hFont = m_font.GetResourceHandle(); if (hFont == (HFONT) NULL) { - wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); + wxLogDebug(wxT("::SelectObject failed in wxPMDCImpl::SetFont.")); } if (!m_hOldFont) m_hOldFont = (WXHFONT) hFont; } -} // end of wxDC::SetFont +} // end of wxPMDCImpl::SetFont -void wxDC::SetPen( +void wxPMDCImpl::SetPen( const wxPen& rPen ) { - wxCHECK_RET( Ok(), wxT("invalid window dc") ); - if (m_pen == rPen) return; m_pen = rPen; - if (!m_pen.Ok()) + if (!m_pen.IsOk()) return; if (m_hOldPen) m_hOldPen = 0L; m_pen = rPen; - if (!m_pen.Ok()) + if (!m_pen.IsOk()) { if (m_hOldPen) { @@ -1239,7 +1958,7 @@ void wxDC::SetPen( m_hOldPen = 0L; } - if (m_pen.Ok()) + if (m_pen.IsOk()) { if (m_pen.GetResourceHandle()) { @@ -1247,26 +1966,25 @@ void wxDC::SetPen( if (!m_hOldPen) m_hOldPen = m_pen.GetPS(); } + ::GpiSetColor(m_hPS, m_pen.GetColour().GetPixel()); } } -void wxDC::SetBrush( +void wxPMDCImpl::SetBrush( const wxBrush& rBrush ) { - wxCHECK_RET( Ok(), wxT("invalid window dc") ); - if (m_hOldBrush) m_hOldBrush = 0L; m_brush = rBrush; - if (!m_brush.Ok()) + if (!m_brush.IsOk()) if (m_brush == rBrush) return; - if (!m_brush.Ok()) + if (!m_brush.IsOk()) if (m_hOldBrush) m_hOldBrush = 0L; - if (!m_brush.Ok()) + if (!m_brush.IsOk()) { if (m_hOldBrush) { @@ -1275,7 +1993,7 @@ void wxDC::SetBrush( m_hOldBrush = 0L; } - if (m_brush.Ok()) + if (m_brush.IsOk()) { if (m_brush.GetResourceHandle()) { @@ -1284,75 +2002,35 @@ void wxDC::SetBrush( m_hOldBrush = (WXHWND)m_brush.GetPS(); } } -} // end of wxDC::SetBrush +} // end of wxPMDCImpl::SetBrush -void wxDC::SetBackground( - const wxBrush& rBrush -) +void wxPMDCImpl::SetBackground(const wxBrush& rBrush) { m_backgroundBrush = rBrush; - if (!m_backgroundBrush.Ok()) - return; - if (m_pCanvas) - { - bool bCustomColours = TRUE; - // - // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to - // change background colours from the control-panel specified colours. - // - if (m_pCanvas->IsKindOf(CLASSINFO(wxWindow)) && - ((m_pCanvas->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS)) - bCustomColours = FALSE; - if (bCustomColours) - { - if (m_backgroundBrush.GetStyle()==wxTRANSPARENT) - { - m_pCanvas->SetTransparent(TRUE); - } - else - { - // - // Setting the background brush of a DC - // doesn't affect the window background colour. However, - // I'm leaving in the transparency setting because it's needed by - // various controls (e.g. wxStaticText) to determine whether to draw - // transparently or not. TODO: maybe this should be a new function - // wxWindow::SetTransparency(). Should that apply to the child itself, or the - // parent? - // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour()); - // - m_pCanvas->SetTransparent(FALSE); - } - } + if (m_backgroundBrush.IsOk()) + { + (void)::GpiSetBackColor((HPS)m_hPS, m_backgroundBrush.GetColour().GetPixel()); } - COLORREF vNewColor = m_backgroundBrush.GetColour().GetPixel(); - (void)::GpiSetBackColor((HPS)m_hPS, (LONG)vNewColor); -} // end of wxDC::SetBackground +} // end of wxPMDCImpl::SetBackground -void wxDC::SetBackgroundMode( - int nMode -) +void wxPMDCImpl::SetBackgroundMode(int nMode) { m_backgroundMode = nMode; -} // end of wxDC::SetBackgroundMode +} // end of wxPMDCImpl::SetBackgroundMode -void wxDC::SetLogicalFunction( - int nFunction -) +void wxPMDCImpl::SetLogicalFunction(wxRasterOperationMode nFunction) { m_logicalFunction = nFunction; SetRop((WXHDC)m_hDC); -} // wxDC::SetLogicalFunction +} // wxPMDCImpl::SetLogicalFunction -void wxDC::SetRop( - WXHDC hDC -) +void wxPMDCImpl::SetRop(WXHDC hDC) { if (!hDC || m_logicalFunction < 0) return; - LONG lCRop; + LONG lCRop; switch (m_logicalFunction) { case wxXOR: @@ -1407,33 +2085,31 @@ void wxDC::SetRop( break; } ::GpiSetMix((HPS)hDC, lCRop); -} // end of wxDC::SetRop +} // end of wxPMDCImpl::SetRop -bool wxDC::StartDoc( - const wxString& rsMessage -) +bool wxPMDCImpl::StartDoc( const wxString& WXUNUSED(rsMessage) ) { - // We might be previewing, so return TRUE to let it continue. - return TRUE; -} // end of wxDC::StartDoc + // We might be previewing, so return true to let it continue. + return true; +} // end of wxPMDCImpl::StartDoc -void wxDC::EndDoc() +void wxPMDCImpl::EndDoc() { -} // end of wxDC::EndDoc +} // end of wxPMDCImpl::EndDoc -void wxDC::StartPage() +void wxPMDCImpl::StartPage() { -} // end of wxDC::StartPage +} // end of wxPMDCImpl::StartPage -void wxDC::EndPage() +void wxPMDCImpl::EndPage() { -} // end of wxDC::EndPage +} // end of wxPMDCImpl::EndPage // --------------------------------------------------------------------------- // text metrics // --------------------------------------------------------------------------- -wxCoord wxDC::GetCharHeight() const +wxCoord wxPMDCImpl::GetCharHeight() const { FONTMETRICS vFM; // metrics structure @@ -1444,7 +2120,7 @@ wxCoord wxDC::GetCharHeight() const return YDEV2LOGREL(vFM.lXHeight); } -wxCoord wxDC::GetCharWidth() const +wxCoord wxPMDCImpl::GetCharWidth() const { FONTMETRICS vFM; // metrics structure @@ -1455,13 +2131,13 @@ wxCoord wxDC::GetCharWidth() const return XDEV2LOGREL(vFM.lAveCharWidth); } -void wxDC::DoGetTextExtent( +void wxPMDCImpl::DoGetTextExtent( const wxString& rsString , wxCoord* pvX , wxCoord* pvY , wxCoord* pvDescent , wxCoord* pvExternalLeading -, wxFont* pTheFont +, const wxFont* pTheFont ) const { POINTL avPoint[TXTBOX_COUNT]; @@ -1471,24 +2147,30 @@ void wxDC::DoGetTextExtent( int l; FONTMETRICS vFM; // metrics structure BOOL bRc; - char* pStr; ERRORID vErrorCode; // last error id code wxFont* pFontToUse = (wxFont*)pTheFont; - char zMsg[128]; // DEBUG + wxChar zMsg[128]; // DEBUG wxString sError; if (!pFontToUse) pFontToUse = (wxFont*)&m_font; l = rsString.length(); - pStr = (PCH) rsString.c_str(); // // In world coordinates. // + if (!m_hPS) + { + (void)wxMessageBox( wxT("wxWidgets core library") + ,"Using uninitialized DC for measuring text!\n" + ,wxICON_INFORMATION + ); + } + bRc = ::GpiQueryTextBox( m_hPS ,l - ,pStr + ,rsString.char_str() ,TXTBOX_COUNT // return maximum information ,avPoint // array of coordinates points ); @@ -1497,8 +2179,8 @@ void wxDC::DoGetTextExtent( vErrorCode = ::WinGetLastError(wxGetInstance()); sError = wxPMErrorToStr(vErrorCode); // DEBUG - sprintf(zMsg, "GpiQueryTextBox for %s: failed with Error: %x - %s", pStr, vErrorCode, sError.c_str()); - (void)wxMessageBox( "wxWindows Menu sample" + wxSprintf(zMsg, wxT("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString.c_str(), vErrorCode, sError.c_str()); + (void)wxMessageBox( wxT("wxWidgets core library") ,zMsg ,wxICON_INFORMATION ); @@ -1530,21 +2212,21 @@ void wxDC::DoGetTextExtent( *pvExternalLeading = vFM.lExternalLeading; } -void wxDC::SetMapMode( - int nMode +void wxPMDCImpl::SetMapMode( + wxMappingMode nMode ) { int nPixelWidth = 0; int nPixelHeight = 0; int nMmWidth = 1; int nMmHeight = 1; - LONG lArray[CAPS_VERTICAL_RESOLUTION]; + LONG lArray[CAPS_VERTICAL_RESOLUTION+1]; m_mappingMode = nMode; if(::DevQueryCaps( m_hDC - ,CAPS_FAMILY - ,CAPS_VERTICAL_RESOLUTION + ,CAPS_FAMILY // id of first item + ,CAPS_VERTICAL_RESOLUTION+1 // number of items wanted ,lArray )) { @@ -1556,15 +2238,15 @@ void wxDC::SetMapMode( lHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter lVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter nMmWidth = (lHorzRes/1000) * nPixelWidth; - nMmWidth = (lVertRes/1000) * nPixelHeight; + nMmHeight = (lVertRes/1000) * nPixelHeight; } if ((nPixelWidth == 0) || (nPixelHeight == 0) || (nMmWidth == 0) || (nMmHeight == 0)) { return; } - double dMm2pixelsX = nPixelWidth/nMmWidth; - double dMm2pixelsY = nPixelHeight/nMmHeight; + double dMm2pixelsX = nPixelWidth/(double)nMmWidth; + double dMm2pixelsY = nPixelHeight/(double)nMmHeight; switch (nMode) { @@ -1594,6 +2276,7 @@ void wxDC::SetMapMode( m_logicalScaleY = 1.0; break; } + SIZEL vSize; ULONG ulOptions; @@ -1603,45 +2286,29 @@ void wxDC::SetMapMode( ulOptions = PU_ARBITRARY | GPIF_DEFAULT; ::GpiSetPS(m_hPS, &vSize, ulOptions); } - m_nWindowExtX = (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT); - m_nWindowExtY = (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT); - // ???? -}; // end of wxDC::SetMapMode + ComputeScaleAndOrigin(); -void wxDC::SetUserScale( - double dX -, double dY -) +}; // end of wxPMDCImpl::SetMapMode + +void wxPMDCImpl::SetUserScale( double dX, + double dY ) { m_userScaleX = dX; m_userScaleY = dY; SetMapMode(m_mappingMode); -} // end of wxDC::SetUserScale +} // end of wxPMDCImpl::SetUserScale -void wxDC::SetAxisOrientation( - bool bXLeftRight -, bool bYBottomUp -) +void wxPMDCImpl::SetAxisOrientation( bool bXLeftRight, + bool bYBottomUp ) { m_signX = bXLeftRight ? 1 : -1; m_signY = bYBottomUp ? -1 : 1; SetMapMode(m_mappingMode); -} // end of wxDC::SetAxisOrientation - -void wxDC::SetSystemScale( - double dX -, double dY -) -{ - m_scaleX = dX; - m_scaleY = dY; - - SetMapMode(m_mappingMode); -} // end of wxDC::SetSystemScale +} // end of wxPMDCImpl::SetAxisOrientation -void wxDC::SetLogicalOrigin( +void wxPMDCImpl::SetLogicalOrigin( wxCoord vX , wxCoord vY ) @@ -1658,9 +2325,9 @@ void wxDC::SetLogicalOrigin( ::GpiSetPageViewport( m_hPS ,&vRect ); -}; // end of wxDC::SetLogicalOrigin +}; // end of wxPMDCImpl::SetLogicalOrigin -void wxDC::SetDeviceOrigin( +void wxPMDCImpl::SetDeviceOrigin( wxCoord vX , wxCoord vY ) @@ -1679,81 +2346,46 @@ void wxDC::SetDeviceOrigin( ::GpiSetPageViewport( m_hPS ,&vRect ); -}; // end of wxDC::SetDeviceOrigin - -// --------------------------------------------------------------------------- -// coordinates transformations -// --------------------------------------------------------------------------- - -wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const -{ - return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX); -} - -wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const -{ - return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX)); -} - -wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const -{ - return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY); -} - -wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const -{ - return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY)); -} - -wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const -{ - return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX); -} - -wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const -{ - return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX); -} - -wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const -{ - return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY); -} - -wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const -{ - return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY); -} +}; // end of wxPMDCImpl::SetDeviceOrigin // --------------------------------------------------------------------------- // bit blit // --------------------------------------------------------------------------- -bool wxDC::DoBlit( - wxCoord vXdest -, wxCoord vYdest -, wxCoord vWidth -, wxCoord vHeight -, wxDC* pSource -, wxCoord vXsrc -, wxCoord vYsrc -, int nRop -, bool bUseMask -) +bool wxPMDCImpl::DoBlit( wxCoord vXdest, + wxCoord vYdest, + wxCoord vWidth, + wxCoord vHeight, + wxDC* pSource, + wxCoord vXsrc, + wxCoord vYsrc, + wxRasterOperationMode nRop, + bool bUseMask, + wxCoord WXUNUSED(vXsrcMask), + wxCoord WXUNUSED(vYsrcMask) ) { wxMask* pMask = NULL; CHARBUNDLE vCbnd; COLORREF vOldTextColor; COLORREF vOldBackground = ::GpiQueryBackColor(m_hPS); + wxDCImpl *impl = pSource->GetImpl(); + wxPMDCImpl *pm_impl = wxDynamicCast( impl, wxPMDCImpl ); + if (!pm_impl) + { + // TODO: Do we want to be able to blit + // from other DCs too? + return false; + } + if (bUseMask) { - const wxBitmap& rBmp = pSource->m_vSelectedBitmap; + const wxBitmap& rBmp = pm_impl->GetSelectedBitmap(); pMask = rBmp.GetMask(); - if (!(rBmp.Ok() && pMask && pMask->GetMaskBitmap())) + if (!(rBmp.IsOk() && pMask && pMask->GetMaskBitmap())) { - bUseMask = FALSE; + bUseMask = false; } } @@ -1764,7 +2396,7 @@ bool wxDC::DoBlit( ); vOldTextColor = (COLORREF)vCbnd.lColor; - if (m_textForegroundColour.Ok()) + if (m_textForegroundColour.IsOk()) { vCbnd.lColor = (LONG)m_textForegroundColour.GetPixel(); ::GpiSetAttrs( m_hPS // presentation-space handle @@ -1774,7 +2406,7 @@ bool wxDC::DoBlit( ,&vCbnd // buffer for attributes. ); } - if (m_textBackgroundColour.Ok()) + if (m_textBackgroundColour.IsOk()) { ::GpiSetBackColor(m_hPS, (LONG)m_textBackgroundColour.GetPixel()); } @@ -1801,7 +2433,7 @@ bool wxDC::DoBlit( case wxNOR: lRop = ROP_NOTSRCCOPY; break; default: wxFAIL_MSG( wxT("unsupported logical function") ); - return FALSE; + return false; } bool bSuccess; @@ -1821,14 +2453,10 @@ bool wxDC::DoBlit( HPS hPSBuffer; DEVOPENSTRUC vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; BITMAPINFOHEADER2 vBmpHdr; + HBITMAP hBufBitmap; SIZEL vSize = {0, 0}; LONG rc; - hDCMask = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE); - hDCBuffer = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE); - hPSMask = ::GpiCreatePS(vHabmain, hDCMask, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC); - hPSBuffer = ::GpiCreatePS(vHabmain, hDCBuffer, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC); - memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2)); vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2); vBmpHdr.cx = vWidth; @@ -1836,26 +2464,56 @@ bool wxDC::DoBlit( vBmpHdr.cPlanes = 1; vBmpHdr.cBitCount = 24; - HBITMAP hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL); - POINTL aPoint1[4] = { 0, 0 - ,vWidth, vHeight - ,vXdest, vYdest - ,vXdest + vWidth, vYdest + vHeight +#if wxUSE_DC_CACHEING + { + // + // create a temp buffer bitmap and DCs to access it and the mask + // + wxDCCacheEntry* pDCCacheEntry1 = FindDCInCache( NULL + ,pm_impl->GetHPS() + ); + wxDCCacheEntry* pDCCacheEntry2 = FindDCInCache( pDCCacheEntry1 + ,GetHPS() + ); + wxDCCacheEntry* pBitmapCacheEntry = FindBitmapInCache( GetHPS() + ,vWidth + ,vHeight + ); + + hPSMask = pDCCacheEntry1->m_hPS; + hDCBuffer = (HDC)pDCCacheEntry2->m_hPS; + hBufBitmap = (HBITMAP)pBitmapCacheEntry->m_hBitmap; + wxUnusedVar(hDCMask); + } +#else + { + hDCMask = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE); + hDCBuffer = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE); + hPSMask = ::GpiCreatePS(vHabmain, hDCMask, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC); + hPSBuffer = ::GpiCreatePS(vHabmain, hDCBuffer, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC); + hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL); + } +#endif + + POINTL aPoint1[4] = { {0, 0} + ,{vWidth, vHeight} + ,{vXdest, vYdest} + ,{vXdest + vWidth, vYdest + vHeight} }; - POINTL aPoint2[4] = { 0, 0 - ,vWidth, vHeight - ,vXsrc, vYsrc - ,vXsrc + vWidth, vYsrc + vHeight + POINTL aPoint2[4] = { {0, 0} + ,{vWidth, vHeight} + ,{vXsrc, vYsrc} + ,{vXsrc + vWidth, vYsrc + vHeight} }; - POINTL aPoint3[4] = { vXdest, vYdest - ,vXdest + vWidth, vYdest + vHeight - ,vXsrc, vYsrc - ,vXsrc + vWidth, vYsrc + vHeight + POINTL aPoint3[4] = { {vXdest, vYdest} + ,{vXdest + vWidth, vYdest + vHeight} + ,{vXsrc, vYsrc} + ,{vXsrc + vWidth, vYsrc + vHeight} }; - POINTL aPoint4[4] = { vXdest, vYdest - ,vXdest + vWidth, vYdest + vHeight - ,0, 0 - ,vWidth, vHeight + POINTL aPoint4[4] = { {vXdest, vYdest} + ,{vXdest + vWidth, vYdest + vHeight} + ,{0, 0} + ,{vWidth, vHeight} }; ::GpiSetBitmap(hPSMask, (HBITMAP) pMask->GetMaskBitmap()); ::GpiSetBitmap(hPSBuffer, (HBITMAP) hBufBitmap); @@ -1946,7 +2604,7 @@ bool wxDC::DoBlit( ); if (rc == GPI_ERROR) { - bSuccess = FALSE; + bSuccess = false; wxLogLastError(wxT("BitBlt")); } @@ -1955,23 +2613,25 @@ bool wxDC::DoBlit( // ::GpiSetBitmap(hPSMask, NULLHANDLE); ::GpiSetBitmap(hPSBuffer, NULLHANDLE); +#if !wxUSE_DC_CACHEING ::GpiDestroyPS(hPSMask); ::GpiDestroyPS(hPSBuffer); ::DevCloseDC(hDCMask); ::DevCloseDC(hDCBuffer); ::GpiDeleteBitmap(hBufBitmap); - bSuccess = TRUE; +#endif + bSuccess = true; } else // no mask, just BitBlt() it { - POINTL aPoint[4] = { vXdest, vYdest - ,vXdest + vWidth, vYdest + vHeight - ,vXsrc, vYsrc - ,vXsrc + vWidth, vYsrc + vHeight + POINTL aPoint[4] = { {vXdest, vYdest} + ,{vXdest + vWidth, vYdest + vHeight} + ,{vXsrc, vYsrc} + ,{vXsrc + vWidth, vYsrc + vHeight} }; bSuccess = (::GpiBitBlt( m_hPS - ,pSource->GetHPS() + ,pm_impl->GetHPS() ,4L ,aPoint ,lRop @@ -1993,60 +2653,62 @@ bool wxDC::DoBlit( return bSuccess; } -void wxDC::DoGetSize( - int* pnWidth -, int* pnHeight -) const +void wxPMDCImpl::DoGetSize( int* pnWidth, + int* pnHeight ) const { - LONG lArray[CAPS_HEIGHT]; + LONG lArray[CAPS_HEIGHT+1]; if(::DevQueryCaps( m_hDC ,CAPS_FAMILY - ,CAPS_HEIGHT + ,CAPS_HEIGHT+1 ,lArray )) { - *pnWidth = lArray[CAPS_WIDTH]; - *pnHeight = lArray[CAPS_HEIGHT]; + if (pnWidth) + *pnWidth = lArray[CAPS_WIDTH]; + if (pnHeight) + *pnHeight = lArray[CAPS_HEIGHT]; } -}; // end of wxDC::DoGetSize( +}; // end of wxPMDCImpl::DoGetSize( -void wxDC::DoGetSizeMM( - int* pnWidth -, int* pnHeight -) const +void wxPMDCImpl::DoGetSizeMM( int* pnWidth, + int* pnHeight ) const { - LONG lArray[CAPS_VERTICAL_RESOLUTION]; + LONG lArray[CAPS_VERTICAL_RESOLUTION+1]; if(::DevQueryCaps( m_hDC ,CAPS_FAMILY - ,CAPS_VERTICAL_RESOLUTION + ,CAPS_VERTICAL_RESOLUTION+1 ,lArray )) { - int nWidth; - int nHeight; - int nHorzRes; - int nVertRes; + if(pnWidth) + { + int nWidth = lArray[CAPS_WIDTH]; + int nHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter + // use fp to avoid returning 0 if nHorzRes < 1000 + *pnWidth = (int)((nHorzRes/1000.0) * nWidth); + } - nWidth = lArray[CAPS_WIDTH]; - nHeight = lArray[CAPS_HEIGHT]; - nHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter - nVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter - nWidth = (nHorzRes/1000) * nWidth; - nHeight = (nVertRes/1000) * nHeight; + if(pnHeight) + { + int nHeight = lArray[CAPS_HEIGHT]; + int nVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter + // use fp to avoid returning 0 if nVertRes < 1000 + *pnHeight = (int)((nVertRes/1000.0) * nHeight); + } } -}; // end of wxDC::DoGetSizeMM +}; // end of wxPMDCImpl::DoGetSizeMM -wxSize wxDC::GetPPI() const +wxSize wxPMDCImpl::GetPPI() const { - LONG lArray[CAPS_VERTICAL_RESOLUTION]; - int nWidth; - int nHeight; + LONG lArray[CAPS_VERTICAL_RESOLUTION+1]; + int nWidth = 0; + int nHeight = 0; if(::DevQueryCaps( m_hDC ,CAPS_FAMILY - ,CAPS_VERTICAL_RESOLUTION + ,CAPS_VERTICAL_RESOLUTION+1 ,lArray )) { @@ -2059,33 +2721,15 @@ wxSize wxDC::GetPPI() const nPelHeight = lArray[CAPS_HEIGHT]; nHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter nVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter - nWidth = (nHorzRes/39.3) * nPelWidth; - nHeight = (nVertRes/39.3) * nPelHeight; + nWidth = (int)((nHorzRes/39.3) * nPelWidth); + nHeight = (int)((nVertRes/39.3) * nPelHeight); } - return (wxSize(nWidth,nHeight)); -} // end of wxDC::GetPPI + wxSize ppisize(nWidth, nHeight); + return ppisize; +} // end of wxPMDCImpl::GetPPI -void wxDC::SetLogicalScale( - double dX -, double dY -) +void wxPMDCImpl::SetLogicalScale( double dX, double dY ) { m_logicalScaleX = dX; m_logicalScaleY = dY; -}; // end of wxDC::SetLogicalScale - -#if WXWIN_COMPATIBILITY -void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y, - float *descent, float *externalLeading, - wxFont *theFont, bool use16bit) const -{ - wxCoord x1, y1, descent1, externalLeading1; - GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit); - *x = x1; *y = y1; - if (descent) - *descent = descent1; - if (externalLeading) - *externalLeading = externalLeading1; -} -#endif - +}; // end of wxPMDCImpl::SetLogicalScale