]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/dcbase.cpp
Add markup support to wxOSX/Cocoa wxStaticText and wxButton.
[wxWidgets.git] / src / common / dcbase.cpp
index 3427fe362ea357a1bb2591ffdea01de541eeb3ab..3dea79e650d8a122531f55ac3bbfcf7cc2f4ea5f 100644 (file)
@@ -30,6 +30,7 @@
 #include "wx/dcscreen.h"
 #include "wx/dcprint.h"
 #include "wx/prntbase.h"
+#include "wx/scopeguard.h"
 
 #ifndef WX_PRECOMP
     #include "wx/math.h"
@@ -235,6 +236,12 @@ wxMemoryDC::wxMemoryDC(wxDC *dc)
 
 void wxMemoryDC::SelectObject(wxBitmap& bmp)
 {
+    if ( bmp.IsSameAs(GetSelectedBitmap()) )
+    {
+        // Nothing to do, this bitmap is already selected.
+        return;
+    }
+
     // make sure that the given wxBitmap is not sharing its data with other
     // wxBitmap instances as its contents will be modified by any drawing
     // operation done on this DC
@@ -569,7 +576,7 @@ void wxDCImpl::GetMultiLineTextExtent(const wxString& text,
     wxString curLine;
     for ( wxString::const_iterator pc = text.begin(); ; ++pc )
     {
-        if ( pc == text.end() || *pc == _T('\n') )
+        if ( pc == text.end() || *pc == wxT('\n') )
         {
             if ( curLine.empty() )
             {
@@ -585,7 +592,7 @@ void wxDCImpl::GetMultiLineTextExtent(const wxString& text,
                 if ( !heightLineDefault )
                 {
                     // but we don't know it yet - choose something reasonable
-                    DoGetTextExtent(_T("W"), NULL, &heightLineDefault,
+                    DoGetTextExtent(wxT("W"), NULL, &heightLineDefault,
                                   NULL, NULL, font);
                 }
 
@@ -656,7 +663,7 @@ wxDCImpl::DoStretchBlit(wxCoord xdest, wxCoord ydest,
                         wxCoord ysrcMask)
 {
     wxCHECK_MSG( srcWidth && srcHeight && dstWidth && dstHeight, false,
-                 _T("invalid blit size") );
+                 wxT("invalid blit size") );
 
     // emulate the stretching by modifying the DC scale
     double xscale = (double)srcWidth/dstWidth,
@@ -729,7 +736,6 @@ wxDCImpl::DoDrawPolyPolygon(int n,
 
     int      i, j, lastOfs;
     wxPoint* pts;
-    wxPen    pen;
 
     for (i = j = lastOfs = 0; i < n; i++)
     {
@@ -745,10 +751,11 @@ wxDCImpl::DoDrawPolyPolygon(int n,
         pts[j++] = pts[lastOfs];
     }
 
-    pen = GetPen();
-    SetPen(wxPen(*wxBLACK, 0, wxPENSTYLE_TRANSPARENT));
-    DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
-    SetPen(pen);
+    {
+        wxDCPenChanger setTransp(*m_owner, *wxTRANSPARENT_PEN);
+        DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
+    }
+
     for (i = j = 0; i < n; i++)
     {
         DoDrawLines(count[i], pts+j, xoffset, yoffset);
@@ -1054,8 +1061,9 @@ void wxDCImpl::DoGradientFillConcentric(const wxRect& rect,
                                       const wxColour& destColour,
                                       const wxPoint& circleCenter)
 {
-    //save the old pen color
-    wxColour oldPenColour = m_pen.GetColour();
+    // save the old pen and ensure it is restored on exit
+    const wxPen penOrig = m_pen;
+    wxON_BLOCK_EXIT_SET(m_pen, penOrig);
 
     wxUint8 nR1 = destColour.Red();
     wxUint8 nG1 = destColour.Green();
@@ -1067,45 +1075,52 @@ void wxDCImpl::DoGradientFillConcentric(const wxRect& rect,
 
 
     //Radius
-    wxInt32 cx = rect.GetWidth() / 2;
-    wxInt32 cy = rect.GetHeight() / 2;
-    wxInt32 nRadius;
+    double cx = rect.GetWidth() / 2;
+    double cy = rect.GetHeight() / 2;
+    double dRadius;
     if (cx < cy)
-        nRadius = cx;
+        dRadius = cx;
     else
-        nRadius = cy;
+        dRadius = cy;
 
     //Offset of circle
-    wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2);
-    wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2);
+    double ptX, ptY;
+    ptX = circleCenter.x;
+    ptY = circleCenter.y;
+    double nCircleOffX = ptX - cx;
+    double nCircleOffY = ptY - cy;
+
+    double dGradient;
+    double dx, dy;
 
     for ( wxInt32 x = 0; x < rect.GetWidth(); x++ )
     {
         for ( wxInt32 y = 0; y < rect.GetHeight(); y++ )
         {
             //get color difference
-            wxInt32 nGradient = ((nRadius -
-                                  (wxInt32)sqrt(
-                                    pow((double)(x - cx - nCircleOffX), 2) +
-                                    pow((double)(y - cy - nCircleOffY), 2)
-                                  )) * 100) / nRadius;
+            dx = x;
+            dy = y;
+
+            dGradient = ((dRadius - sqrt(  (dx - cx - nCircleOffX) * (dx - cx - nCircleOffX)
+                                          +(dy - cy - nCircleOffY) * (dy - cy - nCircleOffY)
+                                         )
+                         ) * 100
+                        ) / dRadius;
 
             //normalize Gradient
-            if (nGradient < 0 )
-                nGradient = 0;
+            if (dGradient < 0)
+                dGradient = 0.0;
 
             //get dest colors
-            nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100));
-            nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100));
-            nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100));
+            nR = (wxUint8)(nR1 + ((nR2 - nR1) * dGradient / 100));
+            nG = (wxUint8)(nG1 + ((nG2 - nG1) * dGradient / 100));
+            nB = (wxUint8)(nB1 + ((nB2 - nB1) * dGradient / 100));
 
             //set the pixel
-            m_pen.SetColour(wxColour(nR,nG,nB));
+            SetPen(wxColour(nR,nG,nB));
             DoDrawPoint(x + rect.GetLeft(), y + rect.GetTop());
         }
     }
-    //return old pen color
-    m_pen.SetColour(oldPenColour);
 }
 
 void wxDCImpl::InheritAttributes(wxWindow *win)
@@ -1119,6 +1134,27 @@ void wxDCImpl::InheritAttributes(wxWindow *win)
     SetLayoutDirection(win->GetLayoutDirection());
 }
 
+void wxDCImpl::DoGetFontMetrics(int *height,
+                                int *ascent,
+                                int *descent,
+                                int *internalLeading,
+                                int *externalLeading,
+                                int *averageWidth) const
+{
+    // Average width is typically the same as width of 'x'.
+    wxCoord h, d;
+    DoGetTextExtent("x", averageWidth, &h, &d, externalLeading);
+
+    if ( height )
+        *height = h;
+    if ( ascent )
+        *ascent = h - d;
+    if ( descent )
+        *descent = d;
+    if ( internalLeading )
+        *internalLeading = 0;
+}
+
 //-----------------------------------------------------------------------------
 // wxDC
 //-----------------------------------------------------------------------------
@@ -1205,6 +1241,12 @@ void wxDC::DrawLabel(const wxString& text,
             yUnderscore = 0;
 
     // split the string into lines and draw each of them separately
+    //
+    // NB: while wxDC::DrawText() on some platforms supports drawing multi-line
+    //     strings natively, this is not the case for all of them, notably not
+    //     wxMSW which uses this function for multi-line texts, so we may only
+    //     call DrawText() for single-line strings from here to avoid infinite
+    //     recursion.
     wxString curLine;
     for ( wxString::const_iterator pc = text.begin(); ; ++pc )
     {
@@ -1275,7 +1317,14 @@ void wxDC::DrawLabel(const wxString& text,
         // it should be of the same colour as text
         SetPen(wxPen(GetTextForeground(), 0, wxPENSTYLE_SOLID));
 
-        yUnderscore--;
+        // This adjustment is relatively arbitrary: we need to draw the
+        // underline slightly higher to avoid overflowing the character cell
+        // but whether we should do it 1, 2 or 3 pixels higher is not clear.
+        //
+        // The currently used value seems to be compatible with native MSW
+        // behaviour, i.e. it results in the same appearance of the owner-drawn
+        // and normal labels.
+        yUnderscore -= 2;
 
         DrawLine(startUnderscore, yUnderscore, endUnderscore, yUnderscore);
     }