X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/23e356deb03a3b1f8413b0d9738a667d4c287f71..6cecceddd8700272b1718da266fcc8d7b3ba829b:/src/os2/dc.cpp?ds=sidebyside diff --git a/src/os2/dc.cpp b/src/os2/dc.cpp index 43bc9720fe..8c8d8a66a4 100644 --- a/src/os2/dc.cpp +++ b/src/os2/dc.cpp @@ -22,6 +22,8 @@ #include "wx/dcmemory.h" #include "wx/log.h" #include "wx/icon.h" + #include "wx/msgdlg.h" + #include "wx/module.h" #endif #include "wx/dcprint.h" @@ -33,6 +35,27 @@ IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) +// +// wxWindows 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 +// 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: +// +// 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. +// objy is the height of the object we are going to draw. +// +#define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) + // --------------------------------------------------------------------------- // constants // --------------------------------------------------------------------------- @@ -127,12 +150,200 @@ 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 + */ + +// --------------------------------------------------------------------------- +// wxDCCacheEntry +// --------------------------------------------------------------------------- + +wxList wxDC::m_svBitmapCache; +wxList wxDC::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* wxDC::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 = 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 = 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* wxDC::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 wxDC::FindDCInCache + +void wxDC::AddToBitmapCache( + wxDCCacheEntry* pEntry +) +{ + m_svBitmapCache.Append(pEntry); +} // end of wxDC::AddToBitmapCache + +void wxDC::AddToDCCache( + wxDCCacheEntry* pEntry +) +{ + m_svDCCache.Append(pEntry); +} // end of wxDC::AddToDCCache + +void wxDC::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 wxDC::ClearCache + +// Clean up cache at app exit +class wxDCModule : public wxModule +{ +public: + virtual bool OnInit() { return TRUE; } + virtual void OnExit() { wxDC::ClearCache(); } + +private: + DECLARE_DYNAMIC_CLASS(wxDCModule) +}; // end of CLASS wxDCModule + +IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) + +#endif // ndef for wxUSE_DC_CACHEING + // --------------------------------------------------------------------------- // wxDC // --------------------------------------------------------------------------- wxDC::wxDC(void) { + wxColour vColor; + m_pCanvas = NULL; m_hOldBitmap = 0; @@ -143,52 +354,71 @@ wxDC::wxDC(void) m_bOwnsDC = FALSE; m_hDC = 0; - m_nDCCount = 0; m_hOldPS = NULL; m_hPS = NULL; m_bIsPaintTime = FALSE; // True at Paint Time - m_brush.GetColour().Set("WHITE"); -} + + vColor.InitFromName("BLACK"); + m_pen.SetColour(vColor); + vColor.Set("WHITE"); + m_brush.SetColour(vColor); +} // end of wxDC::wxDC wxDC::~wxDC(void) { -} + if ( m_hDC != 0 ) + { + SelectOldObjects(m_hDC); + + // if we own the HDC, we delete it, otherwise we just release it + + if (m_bOwnsDC) + { + if(m_hPS) + { + ::GpiAssociate(m_hPS, NULLHANDLE); + ::GpiDestroyPS(m_hPS); + } + m_hPS = NULLHANDLE; + ::DevCloseDC((HDC)m_hDC); + } + else + { + // + // Just Dissacociate, not destroy if we don't own the DC + // + if(m_hPS) + { + ::GpiAssociate(m_hPS, NULLHANDLE); + } + } + } +} // end of wxDC::~wxDC // This will select current objects out of the DC, // which is what you have to do before deleting the // DC. -void wxDC::SelectOldObjects(WXHDC dc) +void wxDC::SelectOldObjects( + WXHDC hPS +) { - if (dc) + if (hPS) { if (m_hOldBitmap) { -// ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap); + ::GpiSetBitmap(hPS, (HBITMAP) m_hOldBitmap); if (m_vSelectedBitmap.Ok()) { m_vSelectedBitmap.SetSelectedInto(NULL); } } m_hOldBitmap = 0; - if (m_hOldPen) - { -// ::SelectObject((HDC) dc, (HPEN) m_oldPen); - } + // + // OS/2 has no other native GDI objects to set in a PS/DC like windows + // m_hOldPen = 0; - if (m_hOldBrush) - { -// ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush); - } m_hOldBrush = 0; - if (m_hOldFont) - { -// ::SelectObject((HDC) dc, (HFONT) m_oldFont); - } m_hOldFont = 0; - if (m_hOldPalette) - { -// ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE); - } m_hOldPalette = 0; } @@ -198,7 +428,7 @@ void wxDC::SelectOldObjects(WXHDC dc) m_font = wxNullFont; m_backgroundBrush = wxNullBrush; m_vSelectedBitmap = wxNullBitmap; -} +} // end of wxDC::SelectOldObjects // --------------------------------------------------------------------------- // clipping @@ -217,19 +447,20 @@ void wxDC::SelectOldObjects(WXHDC dc) } void wxDC::DoSetClippingRegion( - wxCoord x -, wxCoord y -, wxCoord width -, wxCoord height + wxCoord vX +, wxCoord vY +, wxCoord vWidth +, wxCoord vHeight ) { RECTL vRect; + vY = OS2Y(vY,vHeight); m_clipping = TRUE; - vRect.xLeft = XLOG2DEV(x); - vRect.yTop = YLOG2DEV(m_vRclPaint.yTop - y); - vRect.xRight = XLOG2DEV(x + width); - vRect.yBottom = YLOG2DEV(m_vRclPaint.yTop - (y + height)); + 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 @@ -283,18 +514,27 @@ bool wxDC::CanDrawBitmap() const bool wxDC::CanGetTextExtent() const { - // What sort of display is it? - int technology = 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY); + LONG lTechnology = 0L; - // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER); - return FALSE; -} + ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY, 1L, &lTechnology); + return (lTechnology == CAPS_TECH_RASTER_DISPLAY) || (lTechnology == CAPS_TECH_RASTER_PRINTER); +} // end of wxDC::CanGetTextExtent int wxDC::GetDepth() const { - // TODO: - return (1); -} + LONG lArray[CAPS_COLOR_BITCOUNT]; + int nBitsPerPixel; + + if(::DevQueryCaps( GetHDC() + ,CAPS_FAMILY + ,CAPS_COLOR_BITCOUNT + ,lArray + )) + { + nBitsPerPixel = (int)lArray[CAPS_COLOR_BITCOUNT]; + } + return nBitsPerPixel; +} // end of wxDC::GetDepth // --------------------------------------------------------------------------- // drawing @@ -302,8 +542,20 @@ int wxDC::GetDepth() const void wxDC::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 void wxDC::DoFloodFill( wxCoord vX @@ -317,7 +569,7 @@ void wxDC::DoFloodFill( LONG lOptions; vPtlPos.x = vX; // Loads x-coordinate - vPtlPos.y = vY; // Loads y-coordinate + vPtlPos.y = OS2Y(vY,0); // Loads y-coordinate ::GpiMove(m_hPS, &vPtlPos); // Sets current position lColor = rCol.GetPixel(); lOptions = FF_BOUNDARY; @@ -325,7 +577,7 @@ void wxDC::DoFloodFill( lOptions = FF_SURFACE; ::GpiFloodFill(m_hPS, lOptions, lColor); -} +} // end of wxDC::DoFloodFill bool wxDC::DoGetPixel( wxCoord vX @@ -337,19 +589,63 @@ bool wxDC::DoGetPixel( LONG lColor; vPoint.x = vX; - vPoint.y = vY; + vPoint.y = OS2Y(vY,0); lColor = ::GpiSetPel(m_hPS, &vPoint); - pCol->Set((unsigned long)lColor); - if(lColor>= 0) - return(TRUE); - else - return(FALSE); -} -void wxDC::DoCrossHair(wxCoord x, wxCoord y) + // + // Get the color of the pen + // + LONG lPencolor = 0x00ffffff; + + if (m_pen.Ok()) + { + lPencolor = m_pen.GetColour().GetPixel(); + } + + // + // return the color of the pixel + // + if(pCol) + pCol->Set( GetRValue(lColor) + ,GetGValue(lColor) + ,GetBValue(lColor) + ); + return(lColor == lPencolor); +} // end of wxDC::DoGetPixel + +void wxDC::DoCrossHair( + wxCoord vX +, wxCoord vY +) { - // TODO -} + vY = OS2Y(vY,0); + + wxCoord vX1 = vX - VIEWPORT_EXTENT; + wxCoord vY1 = vY - VIEWPORT_EXTENT; + wxCoord vX2 = vX + VIEWPORT_EXTENT; + wxCoord vY2 = vY + VIEWPORT_EXTENT; + POINTL vPoint[4]; + + vPoint[0].x = vX1; + vPoint[0].y = vY; + + vPoint[1].x = vX2; + vPoint[1].y = vY; + + ::GpiMove(m_hPS, &vPoint[0]); + ::GpiLine(m_hPS, &vPoint[1]); + + vPoint[2].x = vX; + vPoint[2].y = vY1; + + vPoint[3].x = vX; + vPoint[3].y = vY2; + + ::GpiMove(m_hPS, &vPoint[2]); + ::GpiLine(m_hPS, &vPoint[3]); + CalcBoundingBox(vX1, vY1); + CalcBoundingBox(vX2, vY2); +} // end of wxDC::DoCrossHair void wxDC::DoDrawLine( wxCoord vX1 @@ -360,13 +656,18 @@ void wxDC::DoDrawLine( { POINTL vPoint[2]; + vY1 = OS2Y(vY1,0); + vY2 = OS2Y(vY2,0); + vPoint[0].x = vX1; - vPoint[0].y = m_vRclPaint.yTop - vY1; + vPoint[0].y = vY1; vPoint[1].x = vX2; - vPoint[1].y = m_vRclPaint.yTop - vY2; + vPoint[1].y = vY2; ::GpiMove(m_hPS, &vPoint[0]); ::GpiLine(m_hPS, &vPoint[1]); -} + CalcBoundingBox(vX1, vY1); + CalcBoundingBox(vX2, vY2); +} // end of wxDC::DoDrawLine ////////////////////////////////////////////////////////////////////////////// // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) @@ -460,7 +761,13 @@ void wxDC::DoDrawArc( vPtlArc[1].x = vX2; vPtlArc[1].y = vY2; ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc -} + CalcBoundingBox( (vXc - dRadius) + ,(vYc - dRadius) + ); + CalcBoundingBox( (vXc + dRadius) + ,(vYc + dRadius) + ); +} // end of wxDC::DoDrawArc void wxDC::DoDrawCheckMark( wxCoord vX1 @@ -471,6 +778,8 @@ void wxDC::DoDrawCheckMark( { POINTL vPoint[2]; + vY1 = OS2Y(vY1,vHeight); + vPoint[0].x = vX1; vPoint[0].y = vY1; vPoint[1].x = vX1 + vWidth; @@ -497,7 +806,17 @@ void wxDC::DoDrawCheckMark( ::GpiMove(m_hPS, &vPoint[0]); ::GpiLine(m_hPS, &vPoint[1]); } -} + CalcBoundingBox( vX1 + ,vY1 + ); + + wxCoord vX2 = vX1 + vWidth; + wxCoord vY2 = vY1 + vHeight; + + CalcBoundingBox( vX2 + ,vY2 + ); +} // end of wxDC::DoDrawCheckMark void wxDC::DoDrawPoint( wxCoord vX @@ -505,11 +824,20 @@ void wxDC::DoDrawPoint( ) { POINTL vPoint; + COLORREF vColor = 0x00ffffff; + if (m_pen.Ok()) + { + vColor = m_pen.GetColour().GetPixel(); + } + ::GpiSetColor(m_hPS, vColor); vPoint.x = vX; - vPoint.y = m_vRclPaint.yTop - vY; + vPoint.y = OS2Y(vY,0); ::GpiSetPel(m_hPS, &vPoint); -} + CalcBoundingBox( vX + ,vY + ); +} // end of wxDC::DoDrawPoint void wxDC::DoDrawPolygon( int n @@ -565,8 +893,8 @@ void wxDC::DoDrawPolygon( for(i = 0; i < n; i++) { - vPlgn.aPointl[i].x = vPoints[i].x; // +xoffset; - vPlgn.aPointl[i].y = vPoints[i].y; // +yoffset; + vPlgn.aPointl[i].x = vPoints[i].x; // +xoffset; + vPlgn.aPointl[i].y = OS2Y(vPoints[i].y,0); // +yoffset; } flModel = POLYGON_BOUNDARY; if(nFillStyle == wxWINDING_RULE) @@ -575,13 +903,13 @@ void wxDC::DoDrawPolygon( flModel |= POLYGON_ALTERNATE; vPoint.x = vXoffset; - vPoint.y = vYoffset; + vPoint.y = OS2Y(vYoffset,0); ::GpiSetColor(m_hPS, lBorderColor); ::GpiMove(m_hPS, &vPoint); lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel); free(vPlgn.aPointl); -} +} // end of wxDC::DoDrawPolygon void wxDC::DoDrawLines( int n @@ -590,23 +918,48 @@ void wxDC::DoDrawLines( , wxCoord vYoffset ) { - int i; POINTL vPoint; - vPoint.x = vPoints[0].x + vXoffset; - vPoint.y = vPoints[0].y + vYoffset; - ::GpiMove(m_hPS, &vPoint); + if (vXoffset != 0L || vXoffset != 0L) + { + int i; - LONG lBorderColor = m_pen.GetColour().GetPixel(); + vPoint.x = vPoints[0].x + vXoffset; + vPoint.y = OS2Y(vPoints[0].y + vYoffset,0); + ::GpiMove(m_hPS, &vPoint); - ::GpiSetColor(m_hPS, lBorderColor); - for(i = 1; i < n; i++) + LONG lBorderColor = m_pen.GetColour().GetPixel(); + + ::GpiSetColor(m_hPS, lBorderColor); + for(i = 1; i < n; i++) + { + vPoint.x = vPoints[i].x + vXoffset; + vPoint.y = OS2Y(vPoints[i].y + vYoffset,0); + ::GpiLine(m_hPS, &vPoint); + } + } + else { - vPoint.x = vPoints[0].x + vXoffset; - vPoint.y = vPoints[0].y + vYoffset; - ::GpiLine(m_hPS, &vPoint); + int i; + + CalcBoundingBox( vPoints[i].x + ,vPoints[i].y + ); + vPoint.x = vPoints[0].x; + vPoint.y = OS2Y(vPoints[0].y,0); + ::GpiMove(m_hPS, &vPoint); + + for (i = 0; i < n; i++) + { + CalcBoundingBox( vPoints[i].x + ,vPoints[i].y + ); + vPoint.x = vPoints[i].x; + vPoint.y = OS2Y(vPoints[i].y,0); + ::GpiLine(m_hPS, &vPoint); + } } -} +} // end of wxDC::DoDrawLines void wxDC::DoDrawRectangle( wxCoord vX @@ -621,10 +974,15 @@ void wxDC::DoDrawRectangle( LONG lBorderColor; int nIsTRANSPARENT = 0; + vY = OS2Y(vY,vHeight); + + wxCoord vX2 = vX + vWidth; + wxCoord vY2 = vY + vHeight; + vPoint[0].x = vX; - vPoint[0].y = m_vRclPaint.yTop - (vY + vHeight); + vPoint[0].y = vY; vPoint[1].x = vX + vWidth; - vPoint[1].y = m_vRclPaint.yTop - vY; + vPoint[1].y = vY + vHeight; ::GpiMove(m_hPS, &vPoint[0]); lColor = m_brush.GetColour().GetPixel(); lBorderColor = m_pen.GetColour().GetPixel(); @@ -661,9 +1019,9 @@ void wxDC::DoDrawRectangle( ,lColor ); vPoint[0].x = vX + 1; - vPoint[0].y = m_vRclPaint.yTop - (vY + vHeight) + 1; - vPoint[1].x = vX + vWidth - 2; - vPoint[1].y = m_vRclPaint.yTop - (vY + 2); + vPoint[0].y = vY + 1; + vPoint[1].x = vX + vWidth - 1; + vPoint[1].y = vY + vHeight - 1; ::GpiMove(m_hPS, &vPoint[0]); ::GpiBox( m_hPS ,lControl @@ -672,7 +1030,9 @@ void wxDC::DoDrawRectangle( ,0L ); } -} + CalcBoundingBox(vX, vY); + CalcBoundingBox(vX2, vY2); +} // end of wxDC::DoDrawRectangle void wxDC::DoDrawRoundedRectangle( wxCoord vX @@ -685,6 +1045,11 @@ void wxDC::DoDrawRoundedRectangle( POINTL vPoint[2]; LONG lControl; + 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; @@ -700,7 +1065,9 @@ void wxDC::DoDrawRoundedRectangle( ,(LONG)dRadius // horizontal corner radius ,(LONG)dRadius // vertical corner radius ); -} + CalcBoundingBox(vX, vY); + CalcBoundingBox(vX2, vY2); +} // end of wxDC::DoDrawRoundedRectangle // Draw Ellipse within box (x,y) - (x+width, y+height) void wxDC::DoDrawEllipse( @@ -714,6 +1081,8 @@ void wxDC::DoDrawEllipse( FIXED vFxMult; // Multiplier for ellipse ARCPARAMS vArcp; // Structure for arc parameters + vY = OS2Y(vY,vHeight); + vArcp.lR = 0; vArcp.lQ = vHeight/2; vArcp.lP = vWidth/2; @@ -735,7 +1104,13 @@ void wxDC::DoDrawEllipse( ,DRO_OUTLINE ,vFxMult ); // Draws full arc with center at current position -} + + wxCoord vX2 = (vX + vWidth); + wxCoord vY2 = (vY + vHeight); + + CalcBoundingBox(vX, vY); + CalcBoundingBox(vX2, vY2); +} // end of wxDC::DoDrawEllipse void wxDC::DoDrawEllipticArc( wxCoord vX @@ -755,6 +1130,8 @@ void wxDC::DoDrawEllipticArc( double dFractPart; double dRadius; + vY = OS2Y(vY,vHeight); + dFractPart = modf(dSa,&dIntPart); vFSa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) ); dFractPart = modf(dEa - dSa, &dIntPart); @@ -788,20 +1165,50 @@ void wxDC::DoDrawEllipticArc( ,vFSa ,vFSweepa ); -} + wxCoord vX2 = (vX + vWidth); + wxCoord vY2 = (vY + vHeight); -void wxDC::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y) + CalcBoundingBox(vX, vY); + CalcBoundingBox(vX2, vY2); +} // end of wxDC::DoDrawEllipticArc + +void wxDC::DoDrawIcon( + const wxIcon& rIcon +, wxCoord vX +, wxCoord vY +) { - // TODO: -} + vY = OS2Y(vY,rIcon.GetHeight()); + wxCHECK_RET( rIcon.Ok(), wxT("invalid icon in DrawIcon") ); -void wxDC::DoDrawBitmap( const wxBitmap &bmp - ,wxCoord x, wxCoord y - ,bool useMask - ) + ::WinDrawPointer( GetHPS() + ,vX + ,vY + ,(HPOINTER)GetHiconOf(rIcon) + ,DP_NORMAL + ); + CalcBoundingBox(vX, vY); + CalcBoundingBox(vX + rIcon.GetWidth(), vY + rIcon.GetHeight()); +} // end of wxDC::DoDrawIcon + +void wxDC::DoDrawBitmap( + const wxBitmap& rBmp +, wxCoord vX +, wxCoord vY +, bool bUseMask +) { - // TODO -} + POINTL vPoint = {vX, vY}; + + ::WinDrawBitmap( GetHPS() + ,(HBITMAP)GetHbitmapOf(rBmp) + ,NULL + ,&vPoint + ,0L + ,0L + ,DBM_NORMAL + ); +} // end of wxDC::DoDrawBitmap void wxDC::DoDrawText( const wxString& rsText @@ -809,11 +1216,18 @@ void wxDC::DoDrawText( , wxCoord vY ) { + wxCoord vWidth; + wxCoord vHeight; + DrawAnyText( rsText ,vX ,vY ); -} + + CalcBoundingBox(vX, vY); + GetTextExtent(rsText, &vWidth, &vHeight); + CalcBoundingBox((vX + vWidth), (vY + vHeight)); +} // end of wxDC::DoDrawText void wxDC::DrawAnyText( const wxString& rsText @@ -824,6 +1238,8 @@ void wxDC::DrawAnyText( int nOldBackground = 0; POINTL vPtlStart; LONG lHits; + wxCoord vTextX = 0; + wxCoord vTextY = 0; // // prepare for drawing the text @@ -848,8 +1264,12 @@ void wxDC::DrawAnyText( SetBkMode( m_hPS ,m_backgroundMode ); + GetTextExtent( rsText + ,&vTextX + ,&vTextY + ); vPtlStart.x = vX; - vPtlStart.y = vY; + vPtlStart.y = OS2Y(vY,vTextY); lHits = ::GpiCharStringAt( m_hPS ,&vPtlStart @@ -946,10 +1366,26 @@ void wxDC::DoDrawRotatedText( // set GDI objects // --------------------------------------------------------------------------- -void wxDC::SetPalette(const wxPalette& palette) +void wxDC::SetPalette( + const wxPalette& rPalette +) { - // TODO -} + if (m_hOldFont) + { + m_hOldFont = 0; + } + m_palette = rPalette; + if (!rPalette.Ok()) + { + if (m_hOldFont) + { + m_hOldFont = 0; + } + } + HPALETTE hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE()); + if (!m_hOldPalette) + m_hOldPalette = (WXHPALETTE)hOldPal; +} // end of wxDC::SetPalette void wxDC::SetFont( const wxFont& rFont @@ -1025,15 +1461,15 @@ void wxDC::SetBrush( { wxCHECK_RET( Ok(), wxT("invalid window dc") ); - if (m_brush == rBrush) - return; - m_brush = rBrush; - if (!m_brush.Ok()) - return; - if (m_hOldBrush) m_hOldBrush = 0L; m_brush = rBrush; + if (!m_brush.Ok()) + if (m_brush == rBrush) + return; + if (!m_brush.Ok()) + if (m_hOldBrush) + m_hOldBrush = 0L; if (!m_brush.Ok()) { @@ -1050,77 +1486,153 @@ void wxDC::SetBrush( { m_brush.SetPS(m_hPS); if (!m_hOldBrush) - m_hOldBrush = m_brush.GetPS(); + m_hOldBrush = (WXHWND)m_brush.GetPS(); } } } // end of wxDC::SetBrush -void wxDC::SetBackground(const wxBrush& brush) +void wxDC::SetBackground( + const wxBrush& rBrush +) { - // TODO -} + 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); + } + } + } + COLORREF vNewColor = m_backgroundBrush.GetColour().GetPixel(); + (void)::GpiSetBackColor((HPS)m_hPS, (LONG)vNewColor); +} // end of wxDC::SetBackground void wxDC::SetBackgroundMode( int nMode ) { m_backgroundMode = nMode; -} +} // end of wxDC::SetBackgroundMode -void wxDC::SetLogicalFunction(int function) +void wxDC::SetLogicalFunction( + int nFunction +) { - // TODO -} + m_logicalFunction = nFunction; + SetRop((WXHDC)m_hDC); +} // wxDC::SetLogicalFunction -void wxDC::SetRop(WXHDC dc) +void wxDC::SetRop( + WXHDC hDC +) { - if (!dc || m_logicalFunction < 0) + if (!hDC || m_logicalFunction < 0) return; - int c_rop; - // These may be wrong + LONG lCRop; switch (m_logicalFunction) { -// TODO: Figure this stuff out - // case wxXOR: c_rop = R2_XORPEN; break; -// case wxXOR: c_rop = R2_NOTXORPEN; break; -// case wxINVERT: c_rop = R2_NOT; break; -// case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break; -// case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break; -// case wxCLEAR: c_rop = R2_WHITE; break; -// case wxSET: c_rop = R2_BLACK; break; -// case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break; -// case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break; -// case wxAND: c_rop = R2_MASKPEN; break; -// case wxOR: c_rop = R2_MERGEPEN; break; -// case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break; -// case wxEQUIV: -// case wxNAND: -// case wxCOPY: - default: -// c_rop = R2_COPYPEN; - break; + case wxXOR: + lCRop = FM_XOR; + break; + + case wxINVERT: + lCRop = FM_INVERT; + break; + + case wxOR_REVERSE: + lCRop = FM_MERGESRCNOT; + break; + + case wxAND_REVERSE: + lCRop = FM_NOTMASKSRC; + break; + + case wxCLEAR: + lCRop = FM_ONE; + break; + + case wxSET: + lCRop = FM_ZERO; + break; + + case wxSRC_INVERT: + lCRop = FM_MERGENOTSRC; + break; + + case wxOR_INVERT: + lCRop = FM_MERGESRCNOT; + break; + + case wxAND: + lCRop = FM_AND; + break; + + case wxOR: + lCRop = FM_OR; + break; + + case wxAND_INVERT: + lCRop = FM_SUBTRACT; + break; + + case wxEQUIV: + case wxNAND: + case wxCOPY: + default: + lCRop = FM_OVERPAINT; + break; } -// SetROP2((HDC) dc, c_rop); -} + ::GpiSetMix((HPS)hDC, lCRop); +} // end of wxDC::SetRop -bool wxDC::StartDoc(const wxString& message) +bool wxDC::StartDoc( + const wxString& rsMessage +) { // We might be previewing, so return TRUE to let it continue. return TRUE; -} +} // end of wxDC::StartDoc void wxDC::EndDoc() { -} +} // end of wxDC::EndDoc void wxDC::StartPage() { -} +} // end of wxDC::StartPage void wxDC::EndPage() { -} +} // end of wxDC::EndPage // --------------------------------------------------------------------------- // text metrics @@ -1223,60 +1735,156 @@ void wxDC::DoGetTextExtent( *pvExternalLeading = vFM.lExternalLeading; } -void wxDC::SetMapMode( int mode ) +void wxDC::SetMapMode( + int nMode +) { - // TODO: -}; + int nPixelWidth = 0; + int nPixelHeight = 0; + int nMmWidth = 1; + int nMmHeight = 1; + LONG lArray[CAPS_VERTICAL_RESOLUTION]; + + m_mappingMode = nMode; + + if(::DevQueryCaps( m_hDC + ,CAPS_FAMILY + ,CAPS_VERTICAL_RESOLUTION + ,lArray + )) + { + LONG lHorzRes; + LONG lVertRes; + + nPixelWidth = lArray[CAPS_WIDTH]; + nPixelHeight = lArray[CAPS_HEIGHT]; + lHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter + lVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter + nMmWidth = (lHorzRes/1000) * nPixelWidth; + nMmWidth = (lVertRes/1000) * nPixelHeight; + } + if ((nPixelWidth == 0) || (nPixelHeight == 0) || (nMmWidth == 0) || (nMmHeight == 0)) + { + return; + } + + double dMm2pixelsX = nPixelWidth/nMmWidth; + double dMm2pixelsY = nPixelHeight/nMmHeight; + + switch (nMode) + { + case wxMM_TWIPS: + m_logicalScaleX = (twips2mm * dMm2pixelsX); + m_logicalScaleY = (twips2mm * dMm2pixelsY); + break; + + case wxMM_POINTS: + m_logicalScaleX = (pt2mm * dMm2pixelsX); + m_logicalScaleY = (pt2mm * dMm2pixelsY); + break; + + case wxMM_METRIC: + m_logicalScaleX = dMm2pixelsX; + m_logicalScaleY = dMm2pixelsY; + break; + + case wxMM_LOMETRIC: + m_logicalScaleX = (dMm2pixelsX/10.0); + m_logicalScaleY = (dMm2pixelsY/10.0); + break; + + case wxMM_TEXT: + default: + m_logicalScaleX = 1.0; + m_logicalScaleY = 1.0; + break; + } + SIZEL vSize; + ULONG ulOptions; -void wxDC::SetUserScale(double x, double y) + ulOptions = ::GpiQueryPS(m_hPS, &vSize); + if (!ulOptions & PU_ARBITRARY) + { + ulOptions = PU_ARBITRARY | GPIF_DEFAULT; + ::GpiSetPS(m_hPS, &vSize, ulOptions); + } + m_nWindowExtX = (int)MS_XDEV2LOG(VIEWPORT_EXTENT); + m_nWindowExtY = (int)MS_YDEV2LOG(VIEWPORT_EXTENT); + // ???? +}; // end of wxDC::SetMapMode + +void wxDC::SetUserScale( + double dX +, double dY +) { - m_userScaleX = x; - m_userScaleY = y; + m_userScaleX = dX; + m_userScaleY = dY; SetMapMode(m_mappingMode); -} +} // end of wxDC::SetUserScale -void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp) +void wxDC::SetAxisOrientation( + bool bXLeftRight +, bool bYBottomUp +) { - m_signX = xLeftRight ? 1 : -1; - m_signY = yBottomUp ? -1 : 1; + m_signX = bXLeftRight ? 1 : -1; + m_signY = bYBottomUp ? -1 : 1; SetMapMode(m_mappingMode); -} +} // end of wxDC::SetAxisOrientation -void wxDC::SetSystemScale(double x, double y) +void wxDC::SetSystemScale( + double dX +, double dY +) { - m_scaleX = x; - m_scaleY = y; + m_scaleX = dX; + m_scaleY = dY; SetMapMode(m_mappingMode); -} +} // end of wxDC::SetSystemScale -void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y ) +void wxDC::SetLogicalOrigin( + wxCoord vX +, wxCoord vY +) { - // TODO: -}; + RECTL vRect; + + ::GpiQueryPageViewport( m_hPS + ,&vRect + ); + vRect.xRight -= vX; + vRect.yTop += vY; + vRect.xLeft = vX; + vRect.yBottom = vY; + ::GpiSetPageViewport( m_hPS + ,&vRect + ); +}; // end of wxDC::SetLogicalOrigin void wxDC::SetDeviceOrigin( - wxCoord x -, wxCoord y + wxCoord vX +, wxCoord vY ) { RECTL vRect; - m_deviceOriginX = x; - m_deviceOriginY = y; + m_deviceOriginX = vX; + m_deviceOriginY = vY; ::GpiQueryPageViewport( m_hPS ,&vRect ); - vRect.xLeft += x; - vRect.xRight += x; - vRect.yBottom -= y; - vRect.yTop -= y; + vRect.xLeft += vX; + vRect.xRight += vX; + vRect.yBottom -= vY; + vRect.yTop -= vY; ::GpiSetPageViewport( m_hPS ,&vRect ); -}; +}; // end of wxDC::SetDeviceOrigin // --------------------------------------------------------------------------- // coordinates transformations @@ -1289,7 +1897,8 @@ wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const { - return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX)); + // axis orientation is not taken into account for conversion of a distance + return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_scaleX)); } wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const @@ -1299,7 +1908,8 @@ wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const { - return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY)); + // axis orientation is not taken into account for conversion of a distance + return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_scaleY)); } wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const @@ -1309,7 +1919,8 @@ wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const { - return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX); + // axis orientation is not taken into account for conversion of a distance + return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_scaleX); } wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const @@ -1319,7 +1930,8 @@ wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const { - return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY); + // axis orientation is not taken into account for conversion of a distance + return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_scaleY); } // --------------------------------------------------------------------------- @@ -1336,6 +1948,8 @@ bool wxDC::DoBlit( , wxCoord vYsrc , int nRop , bool bUseMask +, wxCoord vXsrcMask +, wxCoord vYsrcMask ) { wxMask* pMask = NULL; @@ -1418,14 +2032,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; @@ -1433,7 +2043,37 @@ bool wxDC::DoBlit( vBmpHdr.cPlanes = 1; vBmpHdr.cBitCount = 24; - HBITMAP hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL); +#if wxUSE_DC_CACHEING + if (TRUE) + { + // + // create a temp buffer bitmap and DCs to access it and the mask + // + wxDCCacheEntry* pDCCacheEntry1 = FindDCInCache( NULL + ,pSource->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; + } + else +#endif + { + 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); + } + POINTL aPoint1[4] = { 0, 0 ,vWidth, vHeight ,vXdest, vYdest @@ -1552,11 +2192,13 @@ bool wxDC::DoBlit( // ::GpiSetBitmap(hPSMask, NULLHANDLE); ::GpiSetBitmap(hPSBuffer, NULLHANDLE); +#if !wxUSE_DC_CACHEING ::GpiDestroyPS(hPSMask); ::GpiDestroyPS(hPSBuffer); ::DevCloseDC(hDCMask); ::DevCloseDC(hDCBuffer); ::GpiDeleteBitmap(hBufBitmap); +#endif bSuccess = TRUE; } else // no mask, just BitBlt() it @@ -1590,28 +2232,86 @@ bool wxDC::DoBlit( return bSuccess; } -void wxDC::DoGetSize( int* width, int* height ) const +void wxDC::DoGetSize( + int* pnWidth +, int* pnHeight +) const { - // TODO: -}; + LONG lArray[CAPS_HEIGHT]; + + if(::DevQueryCaps( m_hDC + ,CAPS_FAMILY + ,CAPS_HEIGHT + ,lArray + )) + { + *pnWidth = lArray[CAPS_WIDTH]; + *pnHeight = lArray[CAPS_HEIGHT]; + } +}; // end of wxDC::DoGetSize( -void wxDC::DoGetSizeMM( int* width, int* height ) const +void wxDC::DoGetSizeMM( + int* pnWidth +, int* pnHeight +) const { - // TODO: -}; + LONG lArray[CAPS_VERTICAL_RESOLUTION]; + + if(::DevQueryCaps( m_hDC + ,CAPS_FAMILY + ,CAPS_VERTICAL_RESOLUTION + ,lArray + )) + { + int nWidth; + int nHeight; + int nHorzRes; + int nVertRes; + + 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; + } +}; // end of wxDC::DoGetSizeMM wxSize wxDC::GetPPI() const { - int x = 1; - int y = 1; - // TODO: - return (wxSize(x,y)); -} + LONG lArray[CAPS_VERTICAL_RESOLUTION]; + int nWidth; + int nHeight; -void wxDC::SetLogicalScale( double x, double y ) + if(::DevQueryCaps( m_hDC + ,CAPS_FAMILY + ,CAPS_VERTICAL_RESOLUTION + ,lArray + )) + { + int nPelWidth; + int nPelHeight; + int nHorzRes; + int nVertRes; + + nPelWidth = lArray[CAPS_WIDTH]; + 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; + } + return (wxSize(nWidth,nHeight)); +} // end of wxDC::GetPPI + +void wxDC::SetLogicalScale( + double dX +, double dY +) { - // TODO: -}; + m_logicalScaleX = dX; + m_logicalScaleY = dY; +}; // end of wxDC::SetLogicalScale #if WXWIN_COMPATIBILITY void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y,