+ 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
+)
+{
+ wxCoord vWidth;
+ wxCoord vHeight;
+
+ DrawAnyText( rsText
+ ,vX
+ ,vY
+ );
+
+ CalcBoundingBox(vX, vY);
+ GetOwner()->GetTextExtent(rsText, &vWidth, &vHeight);
+ CalcBoundingBox((vX + vWidth), (vY + vHeight));
+} // end of wxPMDCImpl::DoDrawText
+
+void wxPMDCImpl::DrawAnyText( const wxString& rsText,
+ wxCoord vX,
+ wxCoord vY )
+{
+ int nOldBackground = 0;
+ POINTL vPtlStart;
+ LONG lHits;
+ wxCoord vTextX = 0;
+ wxCoord vTextY = 0;
+
+ //
+ // prepare for drawing the text
+ //
+
+ //
+ // Set text color attributes
+ //
+ if (m_textForegroundColour.Ok())
+ {
+ SetTextColor( m_hPS
+ ,(int)m_textForegroundColour.GetPixel()
+ );
+ }
+
+ if (m_textBackgroundColour.Ok())
+ {
+ nOldBackground = SetTextBkColor( m_hPS
+ ,(int)m_textBackgroundColour.GetPixel()
+ );
+ }
+ SetBkMode( m_hPS
+ ,m_backgroundMode
+ );
+ GetOwner()->GetTextExtent( rsText
+ ,&vTextX
+ ,&vTextY
+ );
+ vPtlStart.x = vX;
+ 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.Ok())
+ {
+ m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
+ m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
+ vPtlStart.y = OS2Y(vY,vTextY);
+ }
+ else
+ vPtlStart.y = vY;
+ }
+
+ ::GpiMove(m_hPS, &vPtlStart);
+ lHits = ::GpiCharString( m_hPS
+ ,rsText.length()
+ ,rsText.char_str()
+ );
+ if (lHits != GPI_OK)
+ {
+ wxLogLastError(wxT("TextOut"));
+ }
+
+ //
+ // Restore the old parameters (text foreground colour may be left because
+ // it never is set to anything else, but background should remain
+ // transparent even if we just drew an opaque string)
+ //
+ if (m_textBackgroundColour.Ok())
+ SetTextBkColor( m_hPS
+ ,nOldBackground
+ );
+ SetBkMode( m_hPS
+ ,wxTRANSPARENT
+ );
+}
+
+void wxPMDCImpl::DoDrawRotatedText(
+ const wxString& rsText
+, wxCoord vX
+, wxCoord vY
+, double dAngle
+)
+{
+ if (dAngle == 0.0)
+ {
+ DoDrawText( rsText
+ ,vX
+ ,vY
+ );
+ }
+
+ // TODO:
+ /*
+ if ( angle == 0.0 )
+ {
+ DoDrawText(text, x, y);
+ }
+ else
+ {
+ LOGFONT lf;
+ wxFillLogFont(&lf, &m_font);
+
+ // GDI wants the angle in tenth of degree
+ long angle10 = (long)(angle * 10);
+ lf.lfEscapement = angle10;
+ lf. lfOrientation = angle10;
+
+ HFONT hfont = ::CreateFontIndirect(&lf);
+ if ( !hfont )
+ {
+ wxLogLastError("CreateFont");
+ }
+ else
+ {
+ HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
+
+ DrawAnyText(text, x, y);
+
+ (void)::SelectObject(GetHdc(), hfontOld);
+ }
+
+ // call the bounding box by adding all four vertices of the rectangle
+ // containing the text to it (simpler and probably not slower than
+ // determining which of them is really topmost/leftmost/...)
+ wxCoord w, h;
+ GetTextExtent(text, &w, &h);
+
+ double rad = DegToRad(angle);
+
+ // "upper left" and "upper right"
+ CalcBoundingBox(x, y);
+ CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
+ CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
+
+ // "bottom left" and "bottom right"
+ x += (wxCoord)(h*sin(rad));
+ y += (wxCoord)(h*cos(rad));
+ CalcBoundingBox(x, y);
+ CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
+ }
+*/
+}
+
+// ---------------------------------------------------------------------------
+// set GDI objects
+// ---------------------------------------------------------------------------
+
+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.Ok())
+ {
+ 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
+)
+{
+ 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 wxPMDCImpl::SetPalette
+
+void wxPMDCImpl::SetFont(
+ const wxFont& rFont
+)
+{
+ //
+ // Set the old object temporarily, in case the assignment deletes an object
+ // that's not yet selected out.
+ //
+ if (m_hOldFont)
+ {
+ m_hOldFont = 0;
+ }
+ m_font = rFont;
+ if (!rFont.Ok())
+ {
+ m_hOldFont = 0;
+ }
+
+ m_font.SetPS(m_hPS); // this will realize the font
+
+ if (m_font.Ok())
+ {
+ HFONT hFont = m_font.GetResourceHandle();
+ if (hFont == (HFONT) NULL)
+ {
+ wxLogDebug(wxT("::SelectObject failed in wxPMDCImpl::SetFont."));
+ }
+ if (!m_hOldFont)
+ m_hOldFont = (WXHFONT) hFont;
+ }
+} // end of wxPMDCImpl::SetFont
+
+void wxPMDCImpl::SetPen(
+ const wxPen& rPen
+)
+{
+ if (m_pen == rPen)
+ return;
+ m_pen = rPen;
+ if (!m_pen.Ok())
+ return;
+
+ if (m_hOldPen)
+ m_hOldPen = 0L;
+ m_pen = rPen;
+
+ if (!m_pen.Ok())
+ {
+ if (m_hOldPen)
+ {
+ m_pen.SetPS((HPS)m_hOldPen);
+ }
+ m_hOldPen = 0L;
+ }
+
+ if (m_pen.Ok())
+ {
+ if (m_pen.GetResourceHandle())
+ {
+ m_pen.SetPS(m_hPS);
+ if (!m_hOldPen)
+ m_hOldPen = m_pen.GetPS();
+ }
+ ::GpiSetColor(m_hPS, m_pen.GetColour().GetPixel());
+ }
+}
+
+void wxPMDCImpl::SetBrush(
+ const wxBrush& rBrush
+)
+{
+ 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())
+ {
+ 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 = (WXHWND)m_brush.GetPS();
+ }
+ }
+} // end of wxPMDCImpl::SetBrush
+
+void wxPMDCImpl::SetBackground(const wxBrush& rBrush)
+{
+ m_backgroundBrush = rBrush;
+
+ if (m_backgroundBrush.Ok())
+ {
+ (void)::GpiSetBackColor((HPS)m_hPS, m_backgroundBrush.GetColour().GetPixel());
+ }
+} // end of wxPMDCImpl::SetBackground
+
+void wxPMDCImpl::SetBackgroundMode(int nMode)
+{
+ m_backgroundMode = nMode;
+} // end of wxPMDCImpl::SetBackgroundMode
+
+void wxPMDCImpl::SetLogicalFunction(wxRasterOperationMode nFunction)
+{
+ m_logicalFunction = nFunction;
+ SetRop((WXHDC)m_hDC);
+} // wxPMDCImpl::SetLogicalFunction
+
+void wxPMDCImpl::SetRop(WXHDC hDC)
+{
+ if (!hDC || m_logicalFunction < 0)
+ return;
+
+ LONG lCRop;
+ switch (m_logicalFunction)
+ {
+ 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;
+ }
+ ::GpiSetMix((HPS)hDC, lCRop);
+} // end of wxPMDCImpl::SetRop
+
+bool wxPMDCImpl::StartDoc( const wxString& WXUNUSED(rsMessage) )
+{
+ // We might be previewing, so return true to let it continue.
+ return true;
+} // end of wxPMDCImpl::StartDoc
+
+void wxPMDCImpl::EndDoc()
+{
+} // end of wxPMDCImpl::EndDoc
+
+void wxPMDCImpl::StartPage()
+{
+} // end of wxPMDCImpl::StartPage
+
+void wxPMDCImpl::EndPage()
+{
+} // end of wxPMDCImpl::EndPage
+
+// ---------------------------------------------------------------------------
+// text metrics
+// ---------------------------------------------------------------------------
+
+wxCoord wxPMDCImpl::GetCharHeight() const
+{
+ FONTMETRICS vFM; // metrics structure
+
+ ::GpiQueryFontMetrics( m_hPS
+ ,sizeof(FONTMETRICS)
+ ,&vFM
+ );
+ return YDEV2LOGREL(vFM.lXHeight);
+}
+
+wxCoord wxPMDCImpl::GetCharWidth() const
+{
+ FONTMETRICS vFM; // metrics structure
+
+ ::GpiQueryFontMetrics( m_hPS
+ ,sizeof(FONTMETRICS)
+ ,&vFM
+ );
+ return XDEV2LOGREL(vFM.lAveCharWidth);
+}
+
+void wxPMDCImpl::DoGetTextExtent(
+ const wxString& rsString
+, wxCoord* pvX
+, wxCoord* pvY
+, wxCoord* pvDescent
+, wxCoord* pvExternalLeading
+, const wxFont* pTheFont
+) const
+{
+ POINTL avPoint[TXTBOX_COUNT];
+ POINTL vPtMin;
+ POINTL vPtMax;
+ int i;
+ int l;
+ FONTMETRICS vFM; // metrics structure
+ BOOL bRc;
+ ERRORID vErrorCode; // last error id code
+ wxFont* pFontToUse = (wxFont*)pTheFont;
+
+ wxChar zMsg[128]; // DEBUG
+ wxString sError;
+
+ if (!pFontToUse)
+ pFontToUse = (wxFont*)&m_font;
+ l = rsString.length();
+
+ //
+ // In world coordinates.
+ //
+ if (!m_hPS)
+ {
+ (void)wxMessageBox( _T("wxWidgets core library")
+ ,"Using uninitialized DC for measuring text!\n"
+ ,wxICON_INFORMATION
+ );
+ }
+
+ bRc = ::GpiQueryTextBox( m_hPS
+ ,l
+ ,rsString.char_str()
+ ,TXTBOX_COUNT // return maximum information
+ ,avPoint // array of coordinates points
+ );
+ if(!bRc)
+ {
+ vErrorCode = ::WinGetLastError(wxGetInstance());
+ sError = wxPMErrorToStr(vErrorCode);
+ // DEBUG
+ wxSprintf(zMsg, _T("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString.c_str(), vErrorCode, sError.c_str());
+ (void)wxMessageBox( _T("wxWidgets core library")
+ ,zMsg
+ ,wxICON_INFORMATION
+ );
+ }
+
+ vPtMin.x = avPoint[0].x;
+ vPtMax.x = avPoint[0].x;
+ vPtMin.y = avPoint[0].y;
+ vPtMax.y = avPoint[0].y;
+ for (i = 1; i < 4; i++)
+ {
+ if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x;
+ if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y;
+ if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x;
+ if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y;
+ }
+ ::GpiQueryFontMetrics( m_hPS
+ ,sizeof(FONTMETRICS)
+ ,&vFM
+ );
+
+ if (pvX)
+ *pvX = (wxCoord)(vPtMax.x - vPtMin.x + 1);
+ if (pvY)
+ *pvY = (wxCoord)(vPtMax.y - vPtMin.y + 1);
+ if (pvDescent)
+ *pvDescent = vFM.lMaxDescender;
+ if (pvExternalLeading)
+ *pvExternalLeading = vFM.lExternalLeading;
+}
+
+void wxPMDCImpl::SetMapMode(
+ wxMappingMode nMode
+)
+{
+ int nPixelWidth = 0;
+ int nPixelHeight = 0;
+ int nMmWidth = 1;
+ int nMmHeight = 1;
+ LONG lArray[CAPS_VERTICAL_RESOLUTION+1];
+
+ m_mappingMode = nMode;
+
+ if(::DevQueryCaps( m_hDC
+ ,CAPS_FAMILY // id of first item
+ ,CAPS_VERTICAL_RESOLUTION+1 // number of items wanted
+ ,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;
+ nMmHeight = (lVertRes/1000) * nPixelHeight;
+ }
+ if ((nPixelWidth == 0) || (nPixelHeight == 0) || (nMmWidth == 0) || (nMmHeight == 0))
+ {
+ return;
+ }
+
+ double dMm2pixelsX = nPixelWidth/(double)nMmWidth;
+ double dMm2pixelsY = nPixelHeight/(double)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;
+
+ ulOptions = ::GpiQueryPS(m_hPS, &vSize);
+ if (!ulOptions & PU_ARBITRARY)
+ {
+ ulOptions = PU_ARBITRARY | GPIF_DEFAULT;
+ ::GpiSetPS(m_hPS, &vSize, ulOptions);
+ }
+ ComputeScaleAndOrigin();
+
+}; // end of wxPMDCImpl::SetMapMode
+
+void wxPMDCImpl::SetUserScale( double dX,
+ double dY )
+{
+ m_userScaleX = dX;
+ m_userScaleY = dY;
+
+ SetMapMode(m_mappingMode);
+} // end of wxPMDCImpl::SetUserScale
+
+void wxPMDCImpl::SetAxisOrientation( bool bXLeftRight,
+ bool bYBottomUp )
+{
+ m_signX = bXLeftRight ? 1 : -1;
+ m_signY = bYBottomUp ? -1 : 1;
+
+ SetMapMode(m_mappingMode);
+} // end of wxPMDCImpl::SetAxisOrientation
+
+void wxPMDCImpl::SetLogicalOrigin(
+ wxCoord vX
+, wxCoord vY
+)
+{
+ RECTL vRect;
+
+ ::GpiQueryPageViewport( m_hPS
+ ,&vRect
+ );
+ vRect.xRight -= vX;
+ vRect.yTop += vY;
+ vRect.xLeft = vX;
+ vRect.yBottom = vY;
+ ::GpiSetPageViewport( m_hPS
+ ,&vRect
+ );
+}; // end of wxPMDCImpl::SetLogicalOrigin
+
+void wxPMDCImpl::SetDeviceOrigin(
+ wxCoord vX
+, wxCoord vY
+)
+{
+ RECTL vRect;
+
+ m_deviceOriginX = vX;
+ m_deviceOriginY = vY;
+ ::GpiQueryPageViewport( m_hPS
+ ,&vRect
+ );
+ vRect.xLeft += vX;
+ vRect.xRight += vX;
+ vRect.yBottom -= vY;
+ vRect.yTop -= vY;
+ ::GpiSetPageViewport( m_hPS
+ ,&vRect
+ );
+}; // end of wxPMDCImpl::SetDeviceOrigin
+
+// ---------------------------------------------------------------------------
+// bit blit
+// ---------------------------------------------------------------------------
+
+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 = pm_impl->GetSelectedBitmap();
+
+ 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;
+ HBITMAP hBufBitmap;
+ SIZEL vSize = {0, 0};
+ LONG rc;
+
+ memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
+ vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2);
+ vBmpHdr.cx = vWidth;
+ vBmpHdr.cy = vHeight;
+ vBmpHdr.cPlanes = 1;
+ vBmpHdr.cBitCount = 24;
+
+#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 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);
+#if !wxUSE_DC_CACHEING
+ ::GpiDestroyPS(hPSMask);
+ ::GpiDestroyPS(hPSBuffer);
+ ::DevCloseDC(hDCMask);
+ ::DevCloseDC(hDCBuffer);
+ ::GpiDeleteBitmap(hBufBitmap);
+#endif
+ 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
+ ,pm_impl->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 wxPMDCImpl::DoGetSize( int* pnWidth,
+ int* pnHeight ) const
+{
+ LONG lArray[CAPS_HEIGHT+1];
+
+ if(::DevQueryCaps( m_hDC
+ ,CAPS_FAMILY
+ ,CAPS_HEIGHT+1
+ ,lArray
+ ))
+ {
+ if (pnWidth)
+ *pnWidth = lArray[CAPS_WIDTH];
+ if (pnHeight)
+ *pnHeight = lArray[CAPS_HEIGHT];
+ }
+}; // end of wxPMDCImpl::DoGetSize(
+
+void wxPMDCImpl::DoGetSizeMM( int* pnWidth,
+ int* pnHeight ) const
+{
+ LONG lArray[CAPS_VERTICAL_RESOLUTION+1];
+
+ if(::DevQueryCaps( m_hDC
+ ,CAPS_FAMILY
+ ,CAPS_VERTICAL_RESOLUTION+1
+ ,lArray
+ ))
+ {
+ 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);
+ }
+
+ 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 wxPMDCImpl::DoGetSizeMM
+
+wxSize wxPMDCImpl::GetPPI() const
+{
+ LONG lArray[CAPS_VERTICAL_RESOLUTION+1];
+ int nWidth = 0;
+ int nHeight = 0;
+
+ if(::DevQueryCaps( m_hDC
+ ,CAPS_FAMILY
+ ,CAPS_VERTICAL_RESOLUTION+1
+ ,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 = (int)((nHorzRes/39.3) * nPelWidth);
+ nHeight = (int)((nVertRes/39.3) * nPelHeight);
+ }
+ wxSize ppisize(nWidth, nHeight);
+ return ppisize;
+} // end of wxPMDCImpl::GetPPI
+
+void wxPMDCImpl::SetLogicalScale( double dX, double dY )
+{
+ m_logicalScaleX = dX;
+ m_logicalScaleY = dY;
+}; // end of wxPMDCImpl::SetLogicalScale