X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/51c1d535fc3314e5de95fc4472f4a7e27a2ebeb6..6c34d0ede9d6f7086896a1e4467091f0360846de:/src/os2/dc.cpp diff --git a/src/os2/dc.cpp b/src/os2/dc.cpp index d0a26ad713..6644a2f340 100644 --- a/src/os2/dc.cpp +++ b/src/os2/dc.cpp @@ -143,52 +143,67 @@ 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_bIsPaintTime = FALSE; // True at Paint Time + m_brush.GetColour().Set("WHITE"); +} // end of wxDC::wxDC wxDC::~wxDC(void) { - // TODO: -}; + 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,40 +213,79 @@ void wxDC::SelectOldObjects(WXHDC dc) m_font = wxNullFont; m_backgroundBrush = wxNullBrush; m_vSelectedBitmap = wxNullBitmap; -} +} // end of wxDC::SelectOldObjects // --------------------------------------------------------------------------- // clipping // --------------------------------------------------------------------------- -#define DO_SET_CLIPPING_BOX() \ -{ \ - RECT rect; \ - \ - GetClipBox(GetHdc(), &rect); \ - \ - m_clipX1 = (wxCoord) XDEV2LOG(rect.left); \ - m_clipY1 = (wxCoord) YDEV2LOG(rect.top); \ - m_clipX2 = (wxCoord) XDEV2LOG(rect.right); \ - m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); \ -} - -void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y - ,wxCoord width, wxCoord height - ) +#define DO_SET_CLIPPING_BOX() \ +{ \ + RECTL rect; \ + \ + ::GpiQueryClipBox(m_hPS, &rect); \ + \ + m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft); \ + m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop); \ + m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight); \ + m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ +} + +void wxDC::DoSetClippingRegion( + wxCoord x +, wxCoord y +, wxCoord width +, wxCoord height +) { - // TODO -} + RECTL vRect; -void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region) + 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)); + ::GpiIntersectClipRectangle(m_hPS, &vRect); + DO_SET_CLIPPING_BOX() +} // end of wxDC::DoSetClippingRegion + +void wxDC::DoSetClippingRegionAsRegion( + const wxRegion& rRegion +) { - // TODO -} + wxCHECK_RET(rRegion.GetHRGN(), wxT("invalid clipping region")); + HRGN hRgnOld; + + m_clipping = TRUE; + ::GpiSetClipRegion( m_hPS + ,(HRGN)rRegion.GetHRGN() + ,&hRgnOld + ); + DO_SET_CLIPPING_BOX() +} // end of wxDC::DoSetClippingRegionAsRegion void wxDC::DestroyClippingRegion(void) { - // TODO: -}; + if (m_clipping && m_hPS) + { + HRGN hRgnOld; + RECTL vRect; + + // TODO: this should restore the previous clipped region + // so that OnPaint processing works correctly, and + // the update doesn't get destroyed after the first + // DestroyClippingRegion + vRect.xLeft = XLOG2DEV(0); + vRect.yTop = YLOG2DEV(32000); + vRect.xRight = XLOG2DEV(32000); + vRect.yBottom = YLOG2DEV(0); + + HRGN hRgn = ::GpiCreateRegion(m_hPS, 1, &vRect); + + ::GpiSetClipRegion(m_hPS, hRgn, &hRgnOld); + } + m_clipping = FALSE; +} // end of wxDC::DestroyClippingRegion // --------------------------------------------------------------------------- // query capabilities @@ -244,18 +298,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 @@ -263,7 +326,7 @@ int wxDC::GetDepth() const void wxDC::Clear() { - // TODO + ::GpiErase(m_hPS); } void wxDC::DoFloodFill( @@ -300,17 +363,42 @@ bool wxDC::DoGetPixel( vPoint.x = vX; vPoint.y = vY; lColor = ::GpiSetPel(m_hPS, &vPoint); -// *pCol.Set(lColor); + pCol->Set((unsigned long)lColor); if(lColor>= 0) return(TRUE); - else + else return(FALSE); } -void wxDC::DoCrossHair(wxCoord x, wxCoord y) +void wxDC::DoCrossHair( + wxCoord vX +, wxCoord vY +) { - // TODO -} + 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 = m_vRclPaint.yTop - vY; + + vPoint[1].x = vX2; + vPoint[1].y = m_vRclPaint.yTop - vY; + + ::GpiMove(m_hPS, &vPoint[0]); + ::GpiLine(m_hPS, &vPoint[1]); + + vPoint[2].x = vX; + vPoint[2].y = m_vRclPaint.yTop - vY1; + + vPoint[3].x = vX; + vPoint[3].y = m_vRclPaint.yTop - vY2; + + ::GpiMove(m_hPS, &vPoint[2]); + ::GpiLine(m_hPS, &vPoint[3]); +} // end of wxDC::DoCrossHair void wxDC::DoDrawLine( wxCoord vX1 @@ -322,13 +410,12 @@ void wxDC::DoDrawLine( POINTL vPoint[2]; vPoint[0].x = vX1; - vPoint[0].y = vY1; + vPoint[0].y = m_vRclPaint.yTop - vY1; vPoint[1].x = vX2; - vPoint[1].y = vY2; - // ::GpiSetColor(m_hPS,CLR_RED); //DEbug + vPoint[1].y = m_vRclPaint.yTop - vY2; ::GpiMove(m_hPS, &vPoint[0]); ::GpiLine(m_hPS, &vPoint[1]); -} +} // end of wxDC::DoDrawLine ////////////////////////////////////////////////////////////////////////////// // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) @@ -387,19 +474,13 @@ void wxDC::DoDrawArc( dAnglmid = (dAngl1 + dAngl2)/2. + M_PI; vXm = vXc + dRadius * cos(dAnglmid); vYm = vYc + dRadius * sin(dAnglmid); - DoDrawArc( vX1 - ,vY1 - ,vXm - ,vYm - ,vXc - ,vYc + DoDrawArc( vX1, vY1 + ,vXm, vYm + ,vXc, vYc ); - DoDrawArc( vXm - ,vYm - ,vX2 - ,vY2 - ,vXc - ,vYc + DoDrawArc( vXm, vYm + ,vX2, vY2 + ,vXc, vYc ); return; } @@ -423,12 +504,12 @@ void wxDC::DoDrawArc( vPtlPos.x = vX1; // Loads x-coordinate vPtlPos.y = vY1; // Loads y-coordinate ::GpiMove(m_hPS, &vPtlPos); // Sets current position - vPtlArc[0].x = vXm; - vPtlArc[0].y = vYm; + vPtlArc[0].x = vXm; + vPtlArc[0].y = vYm; vPtlArc[1].x = vX2; vPtlArc[1].y = vY2; ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc -} +} // end of wxDC::DoDrawArc void wxDC::DoDrawCheckMark( wxCoord vX1 @@ -465,7 +546,7 @@ void wxDC::DoDrawCheckMark( ::GpiMove(m_hPS, &vPoint[0]); ::GpiLine(m_hPS, &vPoint[1]); } -} +} // end of wxDC::DoDrawCheckMark void wxDC::DoDrawPoint( wxCoord vX @@ -475,9 +556,9 @@ void wxDC::DoDrawPoint( POINTL vPoint; vPoint.x = vX; - vPoint.y = vY; + vPoint.y = m_vRclPaint.yTop - vY; ::GpiSetPel(m_hPS, &vPoint); -} +} // end of wxDC::DoDrawPoint void wxDC::DoDrawPolygon( int n @@ -549,7 +630,7 @@ void wxDC::DoDrawPolygon( ::GpiMove(m_hPS, &vPoint); lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel); free(vPlgn.aPointl); -} +} // end of wxDC::DoDrawPolygon void wxDC::DoDrawLines( int n @@ -574,7 +655,7 @@ void wxDC::DoDrawLines( vPoint.y = vPoints[0].y + vYoffset; ::GpiLine(m_hPS, &vPoint); } -} +} // end of wxDC::DoDrawLines void wxDC::DoDrawRectangle( wxCoord vX @@ -590,9 +671,9 @@ void wxDC::DoDrawRectangle( int nIsTRANSPARENT = 0; vPoint[0].x = vX; - vPoint[0].y = vY; + vPoint[0].y = m_vRclPaint.yTop - (vY + vHeight); vPoint[1].x = vX + vWidth; - vPoint[1].y = vY - vHeight; //mustdie !!! ?? + vPoint[1].y = m_vRclPaint.yTop - vY; ::GpiMove(m_hPS, &vPoint[0]); lColor = m_brush.GetColour().GetPixel(); lBorderColor = m_pen.GetColour().GetPixel(); @@ -604,8 +685,7 @@ void wxDC::DoDrawRectangle( if(m_brush.GetStyle() == wxTRANSPARENT) lControl = DRO_OUTLINE; -//EK ::GpiSetColor(m_hPS,lBorderColor); - ::GpiSetColor(m_hPS,CLR_GREEN); + ::GpiSetColor(m_hPS, lColor); ::GpiBox( m_hPS // handle to a presentation space ,lControl // draw the box outline ? or ? ,&vPoint[1] // address of the corner @@ -629,6 +709,11 @@ void wxDC::DoDrawRectangle( ::GpiSetColor( m_hPS ,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); + ::GpiMove(m_hPS, &vPoint[0]); ::GpiBox( m_hPS ,lControl ,&vPoint[1] @@ -636,7 +721,7 @@ void wxDC::DoDrawRectangle( ,0L ); } -} +} // end of wxDC::DoDrawRectangle void wxDC::DoDrawRoundedRectangle( wxCoord vX @@ -650,9 +735,9 @@ void wxDC::DoDrawRoundedRectangle( LONG lControl; vPoint[0].x = vX; - vPoint[0].y = vY; + vPoint[0].y = YLOG2DEV(vY) - vHeight; vPoint[1].x = vX + vWidth; - vPoint[1].y = vY + vHeight; + vPoint[1].y = vY; ::GpiMove(m_hPS, &vPoint[0]); lControl = DRO_OUTLINEFILL; //DRO_FILL; @@ -664,7 +749,7 @@ void wxDC::DoDrawRoundedRectangle( ,(LONG)dRadius // horizontal corner radius ,(LONG)dRadius // vertical corner radius ); -} +} // end of wxDC::DoDrawRoundedRectangle // Draw Ellipse within box (x,y) - (x+width, y+height) void wxDC::DoDrawEllipse( @@ -699,7 +784,7 @@ void wxDC::DoDrawEllipse( ,DRO_OUTLINE ,vFxMult ); // Draws full arc with center at current position -} +} // end of wxDC::DoDrawEllipse void wxDC::DoDrawEllipticArc( wxCoord vX @@ -752,20 +837,42 @@ void wxDC::DoDrawEllipticArc( ,vFSa ,vFSweepa ); -} +} // end of wxDC::DoDrawEllipticArc -void wxDC::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y) +void wxDC::DoDrawIcon( + const wxIcon& rIcon +, wxCoord vX +, wxCoord vY +) { - // TODO: -} + wxCHECK_RET( rIcon.Ok(), wxT("invalid icon in DrawIcon") ); + + ::WinDrawPointer( GetHPS() + ,vX + ,vY + ,(HPOINTER)GetHiconOf(rIcon) + ,DP_NORMAL + ); +} // end of wxDC::DoDrawIcon -void wxDC::DoDrawBitmap( const wxBitmap &bmp - ,wxCoord x, wxCoord y - ,bool useMask - ) +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 @@ -925,22 +1032,19 @@ void wxDC::SetFont( // if (m_hOldFont) { -// ::SelectObject(GetHdc(), (HFONT) m_hOldFont); m_hOldFont = 0; } - m_font = rFont; - if (!rFont.Ok()) { - if (m_hOldFont) -// ::SelectObject(GetHdc(), (HFONT) m_hOldFont); m_hOldFont = 0; } - if (m_font.Ok() && m_font.GetResourceHandle()) + m_font.SetPS(m_hPS); // this will realize the font + + if (m_font.Ok()) { - HFONT hFont = (HFONT)0; //::SelectObject(GetHdc(), (HFONT) m_font.GetResourceHandle()); + HFONT hFont = m_font.GetResourceHandle(); if (hFont == (HFONT) NULL) { wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); @@ -948,7 +1052,7 @@ void wxDC::SetFont( if (!m_hOldFont) m_hOldFont = (WXHFONT) hFont; } -} +} // end of wxDC::SetFont void wxDC::SetPen( const wxPen& rPen @@ -962,74 +1066,65 @@ void wxDC::SetPen( if (!m_pen.Ok()) return; - int nWidth = m_pen.GetWidth(); + if (m_hOldPen) + m_hOldPen = 0L; + m_pen = rPen; - if (nWidth <= 0) - { - nWidth = 1; - } - else + if (!m_pen.Ok()) { - double dW = 0.5 + - ( fabs((double) XLOG2DEVREL(nWidth)) + - fabs((double) YLOG2DEVREL(nWidth)) - ) / 2.0; - nWidth = (int)dW; + if (m_hOldPen) + { + m_pen.SetPS((HPS)m_hOldPen); + } + m_hOldPen = 0L; } - wxColour vColor = m_pen.GetColour(); - ::GpiSetColor( m_hPS - ,vColor.GetPixel() - ); //DEbug ?? - - int nLinetype; - int nStyle = m_pen.GetStyle(); - - nLinetype = LINETYPE_DEFAULT; - switch(nStyle) + if (m_pen.Ok()) { - case wxDOT: - nLinetype = LINETYPE_DOT; - break; - - case wxLONG_DASH: - nLinetype = LINETYPE_LONGDASH; - break; - - case wxSHORT_DASH: - nLinetype = LINETYPE_SHORTDASH; - break; - - case wxDOT_DASH: - nLinetype = LINETYPE_DASHDOT; - break; - - case wxTRANSPARENT: - nLinetype = LINETYPE_INVISIBLE; - break; - - case wxSOLID: - nLinetype = LINETYPE_SOLID; - break; + if (m_pen.GetResourceHandle()) + { + m_pen.SetPS(m_hPS); + if (!m_hOldPen) + m_hOldPen = m_pen.GetPS(); + } } - ::GpiSetLineType( m_hPS - ,nLinetype - ); - - nWidth = m_pen.GetWidth(); - ::GpiSetLineWidth( m_hPS - ,MAKEFIXED( nWidth - ,0 - ) - ); } void wxDC::SetBrush( const wxBrush& rBrush ) { - // TODO -} + 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_hOldBrush) + { + m_brush.SetPS((HPS)m_hOldBrush); + } + m_hOldBrush = 0L; + } + + if (m_brush.Ok()) + { + if (m_brush.GetResourceHandle()) + { + m_brush.SetPS(m_hPS); + if (!m_hOldBrush) + m_hOldBrush = m_brush.GetPS(); + } + } +} // end of wxDC::SetBrush void wxDC::SetBackground(const wxBrush& brush) { @@ -1104,14 +1199,24 @@ void wxDC::EndPage() wxCoord wxDC::GetCharHeight() const { - // TODO - return(8); + FONTMETRICS vFM; // metrics structure + + ::GpiQueryFontMetrics( m_hPS + ,sizeof(FONTMETRICS) + ,&vFM + ); + return YDEV2LOGREL(vFM.lXHeight); } wxCoord wxDC::GetCharWidth() const { - // TODO - return(8); + FONTMETRICS vFM; // metrics structure + + ::GpiQueryFontMetrics( m_hPS + ,sizeof(FONTMETRICS) + ,&vFM + ); + return XDEV2LOGREL(vFM.lAveCharWidth); } void wxDC::DoGetTextExtent( @@ -1134,6 +1239,9 @@ void wxDC::DoGetTextExtent( ERRORID vErrorCode; // last error id code wxFont* pFontToUse = (wxFont*)pTheFont; + char zMsg[128]; // DEBUG + wxString sError; + if (!pFontToUse) pFontToUse = (wxFont*)&m_font; l = rsString.length(); @@ -1151,6 +1259,13 @@ void wxDC::DoGetTextExtent( if(!bRc) { 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" + ,zMsg + ,wxICON_INFORMATION + ); } vPtMin.x = avPoint[0].x; @@ -1213,9 +1328,25 @@ void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y ) // TODO: }; -void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y ) +void wxDC::SetDeviceOrigin( + wxCoord x +, wxCoord y +) { - // TODO: + RECTL vRect; + + m_deviceOriginX = x; + m_deviceOriginY = y; + ::GpiQueryPageViewport( m_hPS + ,&vRect + ); + vRect.xLeft += x; + vRect.xRight += x; + vRect.yBottom -= y; + vRect.yTop -= y; + ::GpiSetPageViewport( m_hPS + ,&vRect + ); }; // --------------------------------------------------------------------------- @@ -1266,19 +1397,268 @@ wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const // bit blit // --------------------------------------------------------------------------- -bool wxDC::DoBlit( wxCoord xdest - ,wxCoord ydest - ,wxCoord width - ,wxCoord height - ,wxDC *source - ,wxCoord xsrc - ,wxCoord ysrc - ,int rop - ,bool useMask - ) +bool wxDC::DoBlit( + wxCoord vXdest +, wxCoord vYdest +, wxCoord vWidth +, wxCoord vHeight +, wxDC* pSource +, wxCoord vXsrc +, wxCoord vYsrc +, int nRop +, bool bUseMask +) { - // TODO - return(TRUE); + wxMask* pMask = NULL; + CHARBUNDLE vCbnd; + COLORREF vOldTextColor; + COLORREF vOldBackground = ::GpiQueryBackColor(m_hPS); + + if (bUseMask) + { + const wxBitmap& rBmp = pSource->m_vSelectedBitmap; + + pMask = rBmp.GetMask(); + if (!(rBmp.Ok() && pMask && pMask->GetMaskBitmap())) + { + bUseMask = FALSE; + } + } + + ::GpiQueryAttrs( m_hPS + ,PRIM_CHAR + ,CBB_COLOR + ,&vCbnd + ); + vOldTextColor = (COLORREF)vCbnd.lColor; + + if (m_textForegroundColour.Ok()) + { + vCbnd.lColor = (LONG)m_textForegroundColour.GetPixel(); + ::GpiSetAttrs( m_hPS // presentation-space handle + ,PRIM_CHAR // Char primitive. + ,CBB_COLOR // sets color. + ,0 + ,&vCbnd // buffer for attributes. + ); + } + if (m_textBackgroundColour.Ok()) + { + ::GpiSetBackColor(m_hPS, (LONG)m_textBackgroundColour.GetPixel()); + } + + LONG lRop = ROP_SRCCOPY; + + switch (nRop) + { + case wxXOR: lRop = ROP_SRCINVERT; break; + case wxINVERT: lRop = ROP_DSTINVERT; break; + case wxOR_REVERSE: lRop = 0x00DD0228; break; + case wxAND_REVERSE: lRop = ROP_SRCERASE; break; + case wxCLEAR: lRop = ROP_ZERO; break; + case wxSET: lRop = ROP_ONE; break; + case wxOR_INVERT: lRop = ROP_MERGEPAINT; break; + case wxAND: lRop = ROP_SRCAND; break; + case wxOR: lRop = ROP_SRCPAINT; break; + case wxEQUIV: lRop = 0x00990066; break; + case wxNAND: lRop = 0x007700E6; break; + case wxAND_INVERT: lRop = 0x00220326; break; + case wxCOPY: lRop = ROP_SRCCOPY; break; + case wxNO_OP: lRop = ROP_NOTSRCERASE; break; + case wxSRC_INVERT: lRop = ROP_SRCINVERT; break; + case wxNOR: lRop = ROP_NOTSRCCOPY; break; + default: + wxFAIL_MSG( wxT("unsupported logical function") ); + return FALSE; + } + + bool bSuccess; + + if (bUseMask) + { + // + // Blit bitmap with mask + // + + // + // Create a temp buffer bitmap and DCs/PSs to access it and the mask + // + HDC hDCMask; + HDC hDCBuffer; + HPS hPSMask; + HPS hPSBuffer; + DEVOPENSTRUC vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; + BITMAPINFOHEADER2 vBmpHdr; + 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; + vBmpHdr.cy = vHeight; + 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 + }; + 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 aPoint4[4] = { vXdest, vYdest + ,vXdest + vWidth, vYdest + vHeight + ,0, 0 + ,vWidth, vHeight + }; + ::GpiSetBitmap(hPSMask, (HBITMAP) pMask->GetMaskBitmap()); + ::GpiSetBitmap(hPSBuffer, (HBITMAP) hBufBitmap); + + // + // Copy dest to buffer + // + rc = ::GpiBitBlt( hPSBuffer + ,GetHPS() + ,4L + ,aPoint1 + ,ROP_SRCCOPY + ,BBO_IGNORE + ); + if (rc == GPI_ERROR) + { + wxLogLastError(wxT("BitBlt")); + } + + // + // Copy src to buffer using selected raster op + // + rc = ::GpiBitBlt( hPSBuffer + ,GetHPS() + ,4L + ,aPoint2 + ,lRop + ,BBO_IGNORE + ); + if (rc == GPI_ERROR) + { + wxLogLastError(wxT("BitBlt")); + } + + // + // Set masked area in buffer to BLACK (pixel value 0) + // + COLORREF vPrevBkCol = ::GpiQueryBackColor(GetHPS()); + COLORREF vPrevCol = ::GpiQueryColor(GetHPS()); + + ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); + ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); + + rc = ::GpiBitBlt( hPSBuffer + ,hPSMask + ,4L + ,aPoint2 + ,ROP_SRCAND + ,BBO_IGNORE + ); + if (rc == GPI_ERROR) + { + wxLogLastError(wxT("BitBlt")); + } + + // + // Set unmasked area in dest to BLACK + // + ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); + ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); + rc = ::GpiBitBlt( GetHPS() + ,hPSMask + ,4L + ,aPoint3 + ,ROP_SRCAND + ,BBO_IGNORE + ); + if (rc == GPI_ERROR) + { + wxLogLastError(wxT("BitBlt")); + } + + // + // Restore colours to original values + // + ::GpiSetBackColor(GetHPS(), vPrevBkCol); + ::GpiSetColor(GetHPS(), vPrevCol); + + // + // OR buffer to dest + // + rc = ::GpiBitBlt( GetHPS() + ,hPSMask + ,4L + ,aPoint4 + ,ROP_SRCPAINT + ,BBO_IGNORE + ); + if (rc == GPI_ERROR) + { + bSuccess = FALSE; + wxLogLastError(wxT("BitBlt")); + } + + // + // Tidy up temporary DCs and bitmap + // + ::GpiSetBitmap(hPSMask, NULLHANDLE); + ::GpiSetBitmap(hPSBuffer, NULLHANDLE); + ::GpiDestroyPS(hPSMask); + ::GpiDestroyPS(hPSBuffer); + ::DevCloseDC(hDCMask); + ::DevCloseDC(hDCBuffer); + ::GpiDeleteBitmap(hBufBitmap); + bSuccess = TRUE; + } + else // no mask, just BitBlt() it + { + POINTL aPoint[4] = { vXdest, vYdest + ,vXdest + vWidth, vYdest + vHeight + ,vXsrc, vYsrc + ,vXsrc + vWidth, vYsrc + vHeight + }; + + bSuccess = (::GpiBitBlt( m_hPS + ,pSource->GetHPS() + ,4L + ,aPoint + ,lRop + ,BBO_IGNORE + ) != GPI_ERROR); + if (!bSuccess ) + { + wxLogLastError(wxT("BitBlt")); + } + } + vCbnd.lColor = (LONG)vOldTextColor; + ::GpiSetAttrs( m_hPS // presentation-space handle + ,PRIM_CHAR // Char primitive. + ,CBB_COLOR // sets color. + ,0 + ,&vCbnd // buffer for attributes. + ); + ::GpiSetBackColor(m_hPS, (LONG)vOldBackground); + return bSuccess; } void wxDC::DoGetSize( int* width, int* height ) const @@ -1319,239 +1699,3 @@ void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y, } #endif -// --------------------------------------------------------------------------- -// spline drawing code -// --------------------------------------------------------------------------- - -#if wxUSE_SPLINES - -class wxSpline: public wxObject -{ -public: - int type; - wxList *points; - - wxSpline(wxList *list); - void DeletePoints(); - - // Doesn't delete points - ~wxSpline(); -}; - -void wx_draw_open_spline(wxDC *dc, wxSpline *spline); - -void wx_quadratic_spline(double a1, double b1, double a2, double b2, - double a3, double b3, double a4, double b4); -void wx_clear_stack(); -int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3, - double *y3, double *x4, double *y4); -void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, - double x4, double y4); -static bool wx_spline_add_point(double x, double y); -static void wx_spline_draw_point_array(wxDC *dc); -wxSpline *wx_make_spline(int x1, int y1, int x2, int y2, int x3, int y3); - -void wxDC::DoDrawSpline(wxList *list) -{ - wxSpline spline(list); - - wx_draw_open_spline(this, &spline); -} - -wxList wx_spline_point_list; - -void wx_draw_open_spline(wxDC *dc, wxSpline *spline) -{ - wxPoint *p; - double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; - double x1, y1, x2, y2; - - wxNode *node = spline->points->First(); - p = (wxPoint *)node->Data(); - - x1 = p->x; - y1 = p->y; - - node = node->Next(); - p = (wxPoint *)node->Data(); - - x2 = p->x; - y2 = p->y; - cx1 = (double)((x1 + x2) / 2); - cy1 = (double)((y1 + y2) / 2); - cx2 = (double)((cx1 + x2) / 2); - cy2 = (double)((cy1 + y2) / 2); - - wx_spline_add_point(x1, y1); - - while ((node = node->Next()) != NULL) - { - p = (wxPoint *)node->Data(); - x1 = x2; - y1 = y2; - x2 = p->x; - y2 = p->y; - cx4 = (double)(x1 + x2) / 2; - cy4 = (double)(y1 + y2) / 2; - cx3 = (double)(x1 + cx4) / 2; - cy3 = (double)(y1 + cy4) / 2; - - wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); - - cx1 = cx4; - cy1 = cy4; - cx2 = (double)(cx1 + x2) / 2; - cy2 = (double)(cy1 + y2) / 2; - } - - wx_spline_add_point((double)wx_round(cx1), (double)wx_round(cy1)); - wx_spline_add_point(x2, y2); - - wx_spline_draw_point_array(dc); - -} - -/********************* CURVES FOR SPLINES ***************************** - - The following spline drawing routine is from - - "An Algorithm for High-Speed Curve Generation" - by George Merrill Chaikin, - Computer Graphics and Image Processing, 3, Academic Press, - 1974, 346-349. - - and - - "On Chaikin's Algorithm" by R. F. Riesenfeld, - Computer Graphics and Image Processing, 4, Academic Press, - 1975, 304-310. - -***********************************************************************/ - -#define half(z1, z2) ((z1+z2)/2.0) -#define THRESHOLD 5 - -/* iterative version */ - -void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4, - double b4) -{ - register double xmid, ymid; - double x1, y1, x2, y2, x3, y3, x4, y4; - - wx_clear_stack(); - wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4); - - while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) { - xmid = (double)half(x2, x3); - ymid = (double)half(y2, y3); - if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD && - fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) { - wx_spline_add_point((double)wx_round(x1), (double)wx_round(y1)); - wx_spline_add_point((double)wx_round(xmid), (double)wx_round(ymid)); - } else { - wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3), - (double)half(x3, x4), (double)half(y3, y4), x4, y4); - wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2), - (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid); - } - } -} - - -/* utilities used by spline drawing routines */ - - -typedef struct wx_spline_stack_struct { - double x1, y1, x2, y2, x3, y3, x4, y4; -} -Stack; - -#define SPLINE_STACK_DEPTH 20 -static Stack wx_spline_stack[SPLINE_STACK_DEPTH]; -static Stack *wx_stack_top; -static int wx_stack_count; - -void wx_clear_stack() -{ - wx_stack_top = wx_spline_stack; - wx_stack_count = 0; -} - -void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) -{ - wx_stack_top->x1 = x1; - wx_stack_top->y1 = y1; - wx_stack_top->x2 = x2; - wx_stack_top->y2 = y2; - wx_stack_top->x3 = x3; - wx_stack_top->y3 = y3; - wx_stack_top->x4 = x4; - wx_stack_top->y4 = y4; - wx_stack_top++; - wx_stack_count++; -} - -int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, - double *x3, double *y3, double *x4, double *y4) -{ - if (wx_stack_count == 0) - return (0); - wx_stack_top--; - wx_stack_count--; - *x1 = wx_stack_top->x1; - *y1 = wx_stack_top->y1; - *x2 = wx_stack_top->x2; - *y2 = wx_stack_top->y2; - *x3 = wx_stack_top->x3; - *y3 = wx_stack_top->y3; - *x4 = wx_stack_top->x4; - *y4 = wx_stack_top->y4; - return (1); -} - -static bool wx_spline_add_point(double x, double y) -{ - wxPoint *point = new wxPoint; - point->x = (int) x; - point->y = (int) y; - wx_spline_point_list.Append((wxObject*)point); - return TRUE; -} - -static void wx_spline_draw_point_array(wxDC *dc) -{ - dc->DrawLines(&wx_spline_point_list, 0, 0); - wxNode *node = wx_spline_point_list.First(); - while (node) - { - wxPoint *point = (wxPoint *)node->Data(); - delete point; - delete node; - node = wx_spline_point_list.First(); - } -} - -wxSpline::wxSpline(wxList *list) -{ - points = list; -} - -wxSpline::~wxSpline() -{ -} - -void wxSpline::DeletePoints() -{ - for(wxNode *node = points->First(); node; node = points->First()) - { - wxPoint *point = (wxPoint *)node->Data(); - delete point; - delete node; - } - delete points; -} - - -#endif // wxUSE_SPLINES -