X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c3d434725bd76bc0306b9751e722ed70bd776876..10992a81d39da31b79063387b7b71c0ff68737ce:/src/os2/dc.cpp diff --git a/src/os2/dc.cpp b/src/os2/dc.cpp index 7a95c3ab97..5ddf11b13b 100644 --- a/src/os2/dc.cpp +++ b/src/os2/dc.cpp @@ -1,123 +1,152 @@ ///////////////////////////////////////////////////////////////////////////// // Name: dc.cpp // Purpose: wxDC class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: 01/02/97 +// Created: 10/14/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "dc.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/window.h" + #include "wx/dc.h" + #include "wx/utils.h" + #include "wx/dialog.h" + #include "wx/app.h" + #include "wx/bitmap.h" + #include "wx/dcmemory.h" + #include "wx/log.h" + #include "wx/icon.h" #endif -#include "wx/dc.h" +#include "wx/dcprint.h" -#if !USE_SHARED_LIBRARY -IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) -#endif +#include +#include + +#include "wx/os2/private.h" + + IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) -//----------------------------------------------------------------------------- +// --------------------------------------------------------------------------- // constants -//----------------------------------------------------------------------------- +// --------------------------------------------------------------------------- -#define mm2inches 0.0393700787402 -#define inches2mm 25.4 -#define mm2twips 56.6929133859 -#define twips2mm 0.0176388888889 -#define mm2pt 2.83464566929 -#define pt2mm 0.352777777778 +static const int VIEWPORT_EXTENT = 1000; -//----------------------------------------------------------------------------- -// wxDCBase -//----------------------------------------------------------------------------- +static const int MM_POINTS = 9; +static const int MM_METRIC = 10; -long wxDCBase::DeviceToLogicalX(long x) const -{ - long new_x = x - m_deviceOriginX; - if (new_x > 0) - return (long)((double)(new_x) / m_scaleX + 0.5) * m_signX + m_logicalOriginX; - else - return (long)((double)(new_x) / m_scaleX - 0.5) * m_signX + m_logicalOriginX; -}; +// usually this is defined in math.h +#ifndef M_PI + static const double M_PI = 3.14159265358979323846; +#endif // M_PI -long wxDCBase::DeviceToLogicalY(long y) const -{ - long new_y = y - m_deviceOriginY; - if (new_y > 0) - return (long)((double)(new_y) / m_scaleY + 0.5) * m_signY + m_logicalOriginY; - else - return (long)((double)(new_y) / m_scaleY - 0.5) * m_signY + m_logicalOriginY; -}; +// --------------------------------------------------------------------------- +// private functions +// --------------------------------------------------------------------------- -long wxDCBase::DeviceToLogicalXRel(long x) const -{ - if (x > 0) - return (long)((double)(x) / m_scaleX + 0.5); - else - return (long)((double)(x) / m_scaleX - 0.5); -}; +// convert degrees to radians +static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } -long wxDCBase::DeviceToLogicalYRel(long y) const +int SetTextColor( + HPS hPS +, int nForegroundColour +) { - if (y > 0) - return (long)((double)(y) / m_scaleY + 0.5); - else - return (long)((double)(y) / m_scaleY - 0.5); -}; + CHARBUNDLE vCbnd; + + vCbnd.lColor = nForegroundColour; + ::GpiSetAttrs( hPS // presentation-space handle + ,PRIM_CHAR // Char primitive. + ,CBB_COLOR // sets color. + ,0 // + ,&vCbnd // buffer for attributes. + ); + return 0; +} -long wxDCBase::LogicalToDeviceX(long x) const +int QueryTextBkColor( + HPS hPS +) { - long new_x = x - m_logicalOriginX; - if (new_x > 0) - return (long)((double)(new_x) * m_scaleX + 0.5) * m_signX + m_deviceOriginX; - else - return (long)((double)(new_x) * m_scaleX - 0.5) * m_signX + m_deviceOriginX; -}; + CHARBUNDLE vCbnd; + + ::GpiQueryAttrs( hPS // presentation-space handle + ,PRIM_CHAR // Char primitive. + ,CBB_BACK_COLOR // Background color. + ,&vCbnd // buffer for attributes. + ); + return vCbnd.lBackColor; +} -long wxDCBase::LogicalToDeviceY(long y) const -{ - long new_y = y - m_logicalOriginY; - if (new_y > 0) - return (long)((double)(new_y) * m_scaleY + 0.5) * m_signY + m_deviceOriginY; - else - return (long)((double)(new_y) * m_scaleY - 0.5) * m_signY + m_deviceOriginY; -}; -long wxDCBase::LogicalToDeviceXRel(long x) const +int SetTextBkColor( + HPS hPS +, int nBackgroundColour +) { - if (x > 0) - return (long)((double)(x) * m_scaleX + 0.5); - else - return (long)((double)(x) * m_scaleX - 0.5); -}; + CHARBUNDLE vCbnd; + int rc; + + rc = QueryTextBkColor(hPS); + + vCbnd.lBackColor = nBackgroundColour; + ::GpiSetAttrs(hPS, // presentation-space handle + PRIM_CHAR, // Char primitive. + CBB_BACK_COLOR, // sets color. + 0, + &vCbnd // buffer for attributes. + ); + return rc; +} -long wxDCBase::LogicalToDeviceYRel(long y) const +int SetBkMode( + HPS hPS +, int nBackgroundMode +) { - if (y > 0) - return (long)((double)(y) * m_scaleY + 0.5); + if(nBackgroundMode == wxTRANSPARENT) + ::GpiSetBackMix( hPS + ,BM_LEAVEALONE + ); else - return (long)((double)(y) * m_scaleY - 0.5); -}; + // the background of the primitive takes over whatever is underneath. + ::GpiSetBackMix( hPS + ,BM_OVERPAINT + ); + return 0; +} + +// =========================================================================== +// implementation +// =========================================================================== -//----------------------------------------------------------------------------- +// --------------------------------------------------------------------------- // wxDC -//----------------------------------------------------------------------------- +// --------------------------------------------------------------------------- wxDC::wxDC(void) { - m_owner = NULL; - m_bitmap = NULL; - - m_oldBitmap = 0; - m_oldPen = 0; - m_oldBrush = 0; - m_oldFont = 0; - m_oldPalette = 0; - m_hDC = 0; - m_hDCCount = 0; + m_pCanvas = NULL; + + m_hOldBitmap = 0; + m_hOldPen = 0; + m_hOldBrush = 0; + m_hOldFont = 0; + m_hOldPalette = 0; + + m_bOwnsDC = FALSE; + m_hDC = 0; + m_nDCCount = 0; + m_hOldPS = NULL; + m_hPS = NULL; + m_bIsPaintTime = FALSE;// True at Paint Time }; wxDC::~wxDC(void) @@ -125,115 +154,482 @@ wxDC::~wxDC(void) // TODO: }; +// 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) +{ + if (dc) + { + if (m_hOldBitmap) + { +// ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap); + if (m_vSelectedBitmap.Ok()) + { + m_vSelectedBitmap.SetSelectedInto(NULL); + } + } + m_hOldBitmap = 0; + if (m_hOldPen) + { +// ::SelectObject((HDC) dc, (HPEN) m_oldPen); + } + 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; + } + + m_brush = wxNullBrush; + m_pen = wxNullPen; + m_palette = wxNullPalette; + m_font = wxNullFont; + m_backgroundBrush = wxNullBrush; + m_vSelectedBitmap = wxNullBitmap; +} + +// --------------------------------------------------------------------------- +// 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 + ) +{ + // TODO +} + +void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region) +{ + // TODO +} + void wxDC::DestroyClippingRegion(void) { // TODO: }; -void wxDC::DoGetSize( int* width, int* height ) const +// --------------------------------------------------------------------------- +// query capabilities +// --------------------------------------------------------------------------- + +bool wxDC::CanDrawBitmap() const { - // TODO: -}; + return TRUE; +} -void wxDC::DoGetSizeMM( int* width, int* height ) const +bool wxDC::CanGetTextExtent() const { - // TODO: -}; + // What sort of display is it? + int technology = 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY); -void wxDC::SetMapMode( int mode ) + // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER); + return FALSE; +} + +int wxDC::GetDepth() const { - // TODO: -}; + // TODO: + return (1); +} -void wxDC::SetUserScale( double x, double y ) +// --------------------------------------------------------------------------- +// drawing +// --------------------------------------------------------------------------- + +void wxDC::Clear() { - m_userScaleX = x; - m_userScaleY = y; + // TODO +} - SetMapMode(m_mappingMode); -}; +void wxDC::DoFloodFill( wxCoord x + ,wxCoord y + ,const wxColour& col + ,int style + ) +{ + // TODO +} -void wxDC::SetLogicalScale( double x, double y ) +bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const { - // TODO: -}; + // TODO + return(TRUE); +} -void wxDC::SetLogicalOrigin( long x, long y ) +void wxDC::DoCrossHair(wxCoord x, wxCoord y) { - // TODO: -}; + // TODO +} -void wxDC::SetDeviceOrigin( long x, long y ) +void wxDC::DoDrawLine( + wxCoord vX1 +, wxCoord vY1 +, wxCoord vX2 +, wxCoord vY2 +) { - // TODO: -}; + POINTL vPoint[2]; + + vPoint[0].x = vX1; + vPoint[0].y = vY1; + vPoint[1].x = vX2; + vPoint[1].y = vY2; + // ::GpiSetColor(m_hPS,CLR_RED); //DEbug + ::GpiMove(m_hPS, &vPoint[0]); + ::GpiLine(m_hPS, &vPoint[1]); +} -void wxDC::SetInternalDeviceOrigin( long x, long y ) +void wxDC::DoDrawArc( wxCoord x1, wxCoord y1 + ,wxCoord x2, wxCoord y2 + ,wxCoord xc, wxCoord yc + ) { - // TODO: -}; + // TODO +} -void wxDC::GetInternalDeviceOrigin( long *x, long *y ) +void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, + wxCoord width, wxCoord height) { - // TODO: -}; + // TODO +} -void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) +void wxDC::DoDrawPoint(wxCoord x, wxCoord y) { - // TODO: -}; + // TODO +} +void wxDC::DoDrawPolygon(int n, wxPoint points[] + ,wxCoord xoffset, wxCoord yoffset + ,int fillStyle + ) +{ + // TODO +} -int wxDC::GetDepth() const +void wxDC::DoDrawLines( int n, wxPoint points[] + ,wxCoord xoffset, wxCoord yoffset + ) { - // TODO: - return (1); + // TODO } -wxSize wxDC::GetPPI() const +void wxDC::DoDrawRectangle( + wxCoord vX +, wxCoord vY +, wxCoord vWidth +, wxCoord vHeight +) { - int x = 1; - int y = 1; - // TODO: - return (wxSize(x,y)); + POINTL vPoint[2]; + + vPoint[0].x = vX; + vPoint[0].y = vY; + vPoint[1].x = vX + vWidth; + vPoint[1].y = vY - vHeight; //mustdie !!! ?? + + ::GpiMove(m_hPS, &vPoint[0]); + ::GpiBox( m_hPS // handle to a presentation space + ,DRO_OUTLINE // draw the box outline ? or ? + ,&vPoint[1] // address of the corner + ,0L // horizontal corner radius + ,0L // vertical corner radius + ); } -void wxDC::GetTextExtent( const wxString& string - ,long* x - ,long* y - ,long* decent - ,long* externalLeading - ,wxFont* theFont - ) const + +void wxDC::DoDrawRoundedRectangle( + wxCoord vX +, wxCoord vY +, wxCoord vWidth +, wxCoord vHeight +, double dRadius +) { - // TODO: + POINTL vPoint[2]; + + vPoint[0].x = vX; + vPoint[0].y = vY; + vPoint[1].x = vX + vWidth; + vPoint[1].y = vY + vHeight; //or -height aka mustdie !!! ?? + + ::GpiMove(m_hPS, &vPoint[0]); + ::GpiBox( m_hPS // handle to a presentation space + ,DRO_OUTLINE // draw the box outline ? or ? + ,&vPoint[1] // address of the corner + ,(LONG)dRadius // horizontal corner radius + ,(LONG)dRadius // vertical corner radius + ); } -long wxDC::GetCharWidth() const +void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) { - // TODO - return(1); + // TODO } -long wxDC::GetCharHeight() const +void wxDC::DoDrawEllipticArc( wxCoord x + ,wxCoord y + ,wxCoord w + ,wxCoord h + ,double sa + ,double ea + ) { - // TODO - return(1); + // TODO } -void wxDC::Clear() +void wxDC::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y) { // TODO } -void wxDC::SetFont(const wxFont& font) +void wxDC::DoDrawBitmap( const wxBitmap &bmp + ,wxCoord x, wxCoord y + ,bool useMask + ) { // TODO } -void wxDC::SetPen(const wxPen& pen) +void wxDC::DoDrawText( + const wxString& rsText +, wxCoord vX +, wxCoord vY +) +{ + DrawAnyText( rsText + ,vX + ,vY + ); +} + +void wxDC::DrawAnyText( + const wxString& rsText +, wxCoord vX +, wxCoord vY +) +{ + int nOldBackground = 0; + POINTL vPtlStart; + LONG lHits; + + // + // 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 + ); + vPtlStart.x = vX; + vPtlStart.y = vY; + + lHits = ::GpiCharStringAt( m_hPS + ,&vPtlStart + ,rsText.length() + ,(PCH)rsText.c_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 wxDC::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 wxDC::SetPalette(const wxPalette& palette) { // TODO } + +void wxDC::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) + { +// ::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()) + { + HFONT hFont = (HFONT)0; //::SelectObject(GetHdc(), (HFONT) m_font.GetResourceHandle()); + if (hFont == (HFONT) NULL) + { + wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); + } + if (!m_hOldFont) + m_hOldFont = (WXHFONT) hFont; + } +} + +void wxDC::SetPen( + const wxPen& rPen +) +{ + wxCHECK_RET( Ok(), wxT("invalid window dc") ); + + if (m_pen == rPen) + return; + m_pen = rPen; + if (!m_pen.Ok()) + return; + + int nWidth = m_pen.GetWidth(); + + if (nWidth <= 0) + { + nWidth = 1; + } + else + { + double dW = 0.5 + + ( fabs((double) XLOG2DEVREL(nWidth)) + + fabs((double) YLOG2DEVREL(nWidth)) + ) / 2.0; + nWidth = (int)dW; + } + wxColour vColor = m_pen.GetColour(); + + ::GpiSetColor( m_hPS + ,vColor.GetPixel() + ); //DEbug ?? +} + void wxDC::SetBrush(const wxBrush& brush) { // TODO @@ -244,113 +640,243 @@ void wxDC::SetBackground(const wxBrush& brush) // TODO } +void wxDC::SetBackgroundMode( + int nMode +) +{ + m_backgroundMode = nMode; +} + void wxDC::SetLogicalFunction(int function) { // TODO } -void wxDC::SetBackgroundMode(int mode) +void wxDC::SetRop(WXHDC dc) { - // TODO + if (!dc || m_logicalFunction < 0) + return; + + int c_rop; + // These may be wrong + 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; + } +// SetROP2((HDC) dc, c_rop); } -void wxDC::SetPalette(const wxPalette& palette) +bool wxDC::StartDoc(const wxString& message) { - // TODO + // We might be previewing, so return TRUE to let it continue. + return TRUE; } -void wxDC::DoFloodFill( long x - ,long y - ,const wxColour& col - ,int style - ) +void wxDC::EndDoc() { - // TODO } -bool wxDC::DoGetPixel(long x, long y, wxColour *col) const +void wxDC::StartPage() { - // TODO - return(TRUE); } -void wxDC::DoDrawPoint(long x, long y) +void wxDC::EndPage() { - // TODO } -void wxDC::DoDrawLine(long x1, long y1, long x2, long y2) +// --------------------------------------------------------------------------- +// text metrics +// --------------------------------------------------------------------------- + +wxCoord wxDC::GetCharHeight() const { - // TODO + // TODO + return(8); } -void wxDC::DoDrawArc( long x1, long y1 - ,long x2, long y2 - ,long xc, long yc - ) +wxCoord wxDC::GetCharWidth() const { - // TODO + // TODO + return(8); } -void wxDC::DoDrawEllipticArc( long x - ,long y - ,long w - ,long h - ,double sa - ,double ea - ) +void wxDC::DoGetTextExtent( + const wxString& rsString +, wxCoord* pvX +, wxCoord* pvY +, wxCoord* pvDescent +, wxCoord* pvExternalLeading +, wxFont* pTheFont +) const { - // TODO + POINTL avPoint[TXTBOX_COUNT]; + POINTL vPtMin; + POINTL vPtMax; + int i; + int l; + FONTMETRICS vFM; // metrics structure + BOOL bRc; + char* pStr; + ERRORID vErrorCode; // last error id code + wxFont* pFontToUse = (wxFont*)pTheFont; + + if (!pFontToUse) + pFontToUse = (wxFont*)&m_font; + l = rsString.length(); + pStr = (PCH) rsString.c_str(); + + // + // In world coordinates. + // + bRc = ::GpiQueryTextBox( m_hPS + ,l + ,pStr + ,TXTBOX_COUNT // return maximum information + ,avPoint // array of coordinates points + ); + if(!bRc) + { + vErrorCode = ::WinGetLastError(wxGetInstance()); + } + + 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 wxDC::DoDrawRectangle(long x, long y, long width, long height) +void wxDC::SetMapMode( int mode ) { - // TODO + // TODO: +}; + +void wxDC::SetUserScale(double x, double y) +{ + m_userScaleX = x; + m_userScaleY = y; + + SetMapMode(m_mappingMode); } -void wxDC::DoDrawRoundedRectangle( long x, long y - ,long width, long height - ,double radius - ) +void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp) { - // TODO + m_signX = xLeftRight ? 1 : -1; + m_signY = yBottomUp ? -1 : 1; + + SetMapMode(m_mappingMode); } -void wxDC::DoDrawEllipse(long x, long y, long width, long height) +void wxDC::SetSystemScale(double x, double y) { - // TODO + m_scaleX = x; + m_scaleY = y; + + SetMapMode(m_mappingMode); } -void wxDC::DoCrossHair(long x, long y) +void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y ) { - // TODO + // TODO: +}; + +void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y ) +{ + // TODO: +}; + +// --------------------------------------------------------------------------- +// coordinates transformations +// --------------------------------------------------------------------------- + +wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const +{ + return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX); } -void wxDC::DoDrawIcon(const wxIcon& icon, long x, long y) +wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const { - // TODO + return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX)); } -void wxDC::DoDrawBitmap( const wxBitmap &bmp - ,long x, long y - ,bool useMask - ) +wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const { - // TODO + return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY); } -void wxDC::DoDrawText(const wxString& text, long x, long y) +wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const { - // TODO + return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY)); +} + +wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const +{ + return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX); +} + +wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const +{ + return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX); +} + +wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const +{ + return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY); +} + +wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const +{ + return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY); } -bool wxDC::DoBlit( long xdest - ,long ydest - ,long width - ,long height +// --------------------------------------------------------------------------- +// bit blit +// --------------------------------------------------------------------------- + +bool wxDC::DoBlit( wxCoord xdest + ,wxCoord ydest + ,wxCoord width + ,wxCoord height ,wxDC *source - ,long xsrc - ,long ysrc + ,wxCoord xsrc + ,wxCoord ysrc ,int rop ,bool useMask ) @@ -359,42 +885,277 @@ bool wxDC::DoBlit( long xdest return(TRUE); } -void wxDC::DoDrawLines( int n, wxPoint points[] - ,long xoffset, long yoffset - ) +void wxDC::DoGetSize( int* width, int* height ) const { - // TODO + // TODO: +}; + +void wxDC::DoGetSizeMM( int* width, int* height ) const +{ + // TODO: +}; + +wxSize wxDC::GetPPI() const +{ + int x = 1; + int y = 1; + // TODO: + return (wxSize(x,y)); } -void wxDC::DoDrawPolygon(int n, wxPoint points[] - ,long xoffset, long yoffset - ,int fillStyle - ) +void wxDC::SetLogicalScale( double x, double y ) { - // TODO + // TODO: +}; + +#if WXWIN_COMPATIBILITY +void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y, + float *descent, float *externalLeading, + wxFont *theFont, bool use16bit) const +{ + wxCoord x1, y1, descent1, externalLeading1; + GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit); + *x = x1; *y = y1; + if (descent) + *descent = descent1; + if (externalLeading) + *externalLeading = externalLeading1; } +#endif -void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region) +// --------------------------------------------------------------------------- +// spline drawing code +// --------------------------------------------------------------------------- + +#if wxUSE_SPLINES + +class wxSpline: public wxObject { - // TODO +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); } -void wxDC::DoSetClippingRegion( long x, long y - ,long width, long height - ) +wxList wx_spline_point_list; + +void wx_draw_open_spline(wxDC *dc, wxSpline *spline) { - // TODO + 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); + } -#if wxUSE_SPLINES -void wxDC::DoDrawSpline(wxList *points) +/********************* 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) { - // TODO + 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 -// -// Private functions -// +#endif // wxUSE_SPLINES