]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dc.cpp
compilation fix for non-threaded compilation (threads are still broken
[wxWidgets.git] / src / msw / dc.cpp
index cd18a5005f64c014a16f6dd9f844d94e772ac39b..45c51e9417f3e8d30a713bd31d265bd9e43ec971 100644 (file)
@@ -58,9 +58,7 @@
 
 #include "wx/msw/private.h"
 
-#if !USE_SHARED_LIBRARY
     IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
-#endif
 
 // ---------------------------------------------------------------------------
 // constants
@@ -71,6 +69,18 @@ static const int VIEWPORT_EXTENT = 1000;
 static const int MM_POINTS = 9;
 static const int MM_METRIC = 10;
 
+// usually this is defined in math.h
+#ifndef M_PI
+    static const double M_PI = 3.14159265358979323846;
+#endif // M_PI
+
+// ---------------------------------------------------------------------------
+// private functions
+// ---------------------------------------------------------------------------
+
+// convert degrees to radians
+static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
+
 // ===========================================================================
 // implementation
 // ===========================================================================
@@ -538,15 +548,18 @@ void wxDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,d
     wxCoord x2 = (x+w);
     wxCoord y2 = (y+h);
 
-    const double deg2rad = 3.14159265359 / 180.0;
     int rx1 = XLOG2DEV(x+w/2);
     int ry1 = YLOG2DEV(y+h/2);
     int rx2 = rx1;
     int ry2 = ry1;
-    rx1 += (int)(100.0 * abs(w) * cos(sa * deg2rad));
-    ry1 -= (int)(100.0 * abs(h) * m_signY * sin(sa * deg2rad));
-    rx2 += (int)(100.0 * abs(w) * cos(ea * deg2rad));
-    ry2 -= (int)(100.0 * abs(h) * m_signY * sin(ea * deg2rad));
+
+    sa = DegToRad(sa);
+    ea = DegToRad(ea);
+
+    rx1 += (int)(100.0 * abs(w) * cos(sa));
+    ry1 -= (int)(100.0 * abs(h) * m_signY * sin(sa));
+    rx2 += (int)(100.0 * abs(w) * cos(ea));
+    ry2 -= (int)(100.0 * abs(h) * m_signY * sin(ea));
 
     // draw pie with NULL_PEN first and then outline otherwise a line is
     // drawn from the start and end points to the centre
@@ -625,41 +638,107 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask
 
 void wxDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y)
 {
-    if (m_textForegroundColour.Ok())
-        SetTextColor(GetHdc(), m_textForegroundColour.GetPixel() );
+    DrawAnyText(text, x, y);
+
+    // update the bounding box
+    CalcBoundingBox(x, y);
+
+    wxCoord w, h;
+    GetTextExtent(text, &w, &h);
+    CalcBoundingBox(x + w, y + h);
+}
+
+void wxDC::DrawAnyText(const wxString& text, wxCoord x, wxCoord y)
+{
+    // prepare for drawing the text
+    if ( m_textForegroundColour.Ok() )
+        SetTextColor(GetHdc(), m_textForegroundColour.GetPixel());
 
     DWORD old_background = 0;
-    if (m_textBackgroundColour.Ok())
+    if ( m_textBackgroundColour.Ok() )
     {
         old_background = SetBkColor(GetHdc(), m_textBackgroundColour.GetPixel() );
     }
 
-    if (m_backgroundMode == wxTRANSPARENT)
-        SetBkMode(GetHdc(), TRANSPARENT);
-    else
-        SetBkMode(GetHdc(), OPAQUE);
+    SetBkMode(GetHdc(), m_backgroundMode == wxTRANSPARENT ? TRANSPARENT
+                                                          : OPAQUE);
 
-    (void)TextOut(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), WXSTRINGCAST text, wxStrlen(WXSTRINGCAST text));
+    if ( ::TextOut(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
+                   text.c_str(), text.length()) == 0 )
+    {
+        wxLogLastError("TextOut");
+    }
 
-    if (m_textBackgroundColour.Ok())
+    // 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() )
         (void)SetBkColor(GetHdc(), old_background);
 
-    // background colour is used only for DrawText, otherwise
-    // always TRANSPARENT, RR
     SetBkMode(GetHdc(), TRANSPARENT);
-
-    CalcBoundingBox(x, y);
-
-    wxCoord w, h;
-    GetTextExtent(text, &w, &h);
-    CalcBoundingBox((x + w), (y + h));
 }
 
 void wxDC::DoDrawRotatedText(const wxString& text,
                              wxCoord x, wxCoord y,
                              double angle)
 {
-    wxFAIL_MSG( _T("TODO") );
+    // we test that we have some font because otherwise we should still use the
+    // "else" part below to avoid that DrawRotatedText(angle = 180) and
+    // DrawRotatedText(angle = 0) use different fonts (we can't use the default
+    // font for drawing rotated fonts unfortunately)
+    if ( (angle == 0.0) && m_font.Ok() )
+    {
+        DoDrawText(text, x, y);
+    }
+    else
+    {
+        // NB: don't take DEFAULT_GUI_FONT because it's not TrueType and so
+        //     can't have non zero orientation/escapement
+        wxFont font = m_font.Ok() ? m_font : *wxNORMAL_FONT;
+        HFONT hfont = (HFONT)font.GetResourceHandle();
+        LOGFONT lf;
+        if ( ::GetObject(hfont, sizeof(lf), &lf) == 0 )
+        {
+            wxLogLastError("GetObject(hfont)");
+        }
+
+        // GDI wants the angle in tenth of degree
+        long angle10 = (long)(angle * 10);
+        lf.lfEscapement = angle10;
+        lf. lfOrientation = angle10;
+
+        hfont = ::CreateFontIndirect(&lf);
+        if ( !hfont )
+        {
+            wxLogLastError("CreateFont");
+        }
+        else
+        {
+            HFONT hfontOld = (HFONT)::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));
+
+        // "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));
+    }
 }
 
 // ---------------------------------------------------------------------------
@@ -1151,17 +1230,6 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
         else
 #endif
         {
-            // Old code
-#if 0
-            HDC dc_mask = CreateCompatibleDC((HDC) source->m_hDC);
-            ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap());
-            success = (BitBlt(GetHdc(), xdest1, ydest1, (int)width, (int)height,
-                dc_mask, xsrc1, ysrc1, 0x00220326 /* NOTSRCAND */) != 0);
-            success = (BitBlt(GetHdc(), xdest1, ydest1, (int)width, (int)height,
-                (HDC) source->m_hDC, xsrc1, ysrc1, SRCPAINT) != 0);
-            ::SelectObject(dc_mask, 0);
-            ::DeleteDC(dc_mask);
-#endif
             // New code from Chris Breeze, 15/7/98
             // Blit bitmap with mask
 
@@ -1239,11 +1307,37 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
     }
     else
     {
+        // If we are printing, source colours are screen colours
+        // not printer colours and so we need copy the bitmap
+        // pixel by pixel.
         if (IsKindOf(CLASSINFO(wxPrinterDC)))
         {
-            // If we are printing, source colours are screen colours
-            // not printer colours and so we need copy the bitmap
-            // pixel by pixel.
+            HDC dc_src = (HDC) source->m_hDC;
+               RECT rect;
+               for (int y = 0; y < height; y++)
+               {
+                // This is Stefan Csomor's optimisation, where
+                // identical adjacent pixels are drawn together.
+                // We still need a faster way of drawing bitmaps,
+                // perhaps converting to a DIB first and using SetDIBitsToDevice.
+                   for (int x = 0; x < width; x++)
+                   {
+                       COLORREF col = ::GetPixel(dc_src, x, y) ;
+                       HBRUSH brush = ::CreateSolidBrush( col );
+
+                       rect.left = xdest1 + x;
+                       rect.top = ydest1 + y;
+                       while( (x + 1 < width) && (::GetPixel(dc_src, x + 1, y) == col ) )
+                       {
+                               ++x ;
+                       }
+                       rect.right = xdest1 + x + 1;
+                       rect.bottom = rect.top + 1;
+                       ::FillRect((HDC) m_hDC, &rect, brush);
+                       ::DeleteObject(brush);
+                }
+               }
+/*
             HDC dc_src = (HDC) source->m_hDC;
             RECT rect;
             for (int x = 0; x < width; x++)
@@ -1257,7 +1351,8 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
                     ::DeleteObject(brush);
                 }
             }
-        }
+*/
+           }
         else
         {
             success = (BitBlt(GetHdc(), xdest1, ydest1, (int)width, (int)height, (HDC) source->m_hDC,