+void wxDC::SetMapMode(
+ int nMode
+)
+{
+ 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;
+
+ 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 = dX;
+ m_userScaleY = dY;
+
+ SetMapMode(m_mappingMode);
+} // end of wxDC::SetUserScale
+
+void wxDC::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
+
+void wxDC::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 wxDC::SetLogicalOrigin
+
+void wxDC::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 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
+{
+ // 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
+{
+ return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY);
+}
+
+wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
+{
+ // 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
+{
+ return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX);
+}
+
+wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
+{
+ // 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
+{
+ return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY);
+}
+
+wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
+{
+ // axis orientation is not taken into account for conversion of a distance
+ return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_scaleY);
+}
+
+// ---------------------------------------------------------------------------
+// bit blit
+// ---------------------------------------------------------------------------
+
+bool wxDC::DoBlit( wxCoord vXdest,
+ wxCoord vYdest,
+ wxCoord vWidth,
+ wxCoord vHeight,
+ wxDC* pSource,
+ wxCoord vXsrc,
+ wxCoord vYsrc,
+ int nRop,
+ bool bUseMask,
+ wxCoord WXUNUSED(vXsrcMask),
+ wxCoord WXUNUSED(vYsrcMask) )
+{
+ 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;
+ 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
+ ,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;
+ 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
+ ,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* pnWidth,
+ int* pnHeight ) const
+{
+ 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* pnWidth,
+ int* pnHeight ) const
+{
+ LONG lArray[CAPS_VERTICAL_RESOLUTION];
+
+ if(::DevQueryCaps( m_hDC
+ ,CAPS_FAMILY
+ ,CAPS_VERTICAL_RESOLUTION
+ ,lArray
+ ))
+ {
+ if(pnWidth)
+ {
+ int nWidth = lArray[CAPS_WIDTH];
+ int nHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
+ *pnWidth = (nHorzRes/1000) * nWidth;
+ }
+
+ if(pnHeight)
+ {
+ int nHeight = lArray[CAPS_HEIGHT];
+ int nVertRes = lArray[CAPS_VERTICAL_RESOLUTION]; // returns pel/meter
+ *pnHeight = (nVertRes/1000) * nHeight;
+ }
+ }
+}; // end of wxDC::DoGetSizeMM
+
+wxSize wxDC::GetPPI() const
+{
+ LONG lArray[CAPS_VERTICAL_RESOLUTION];
+ int nWidth = 0;
+ int nHeight = 0;
+
+ 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 = (int)((nHorzRes/39.3) * nPelWidth);
+ nHeight = (int)((nVertRes/39.3) * nPelHeight);
+ }
+ wxSize ppisize(nWidth, nHeight);
+ return ppisize;
+} // end of wxDC::GetPPI
+
+void wxDC::SetLogicalScale( double dX, double dY )
+{
+ m_logicalScaleX = dX;
+ m_logicalScaleY = dY;
+}; // end of wxDC::SetLogicalScale