]> git.saurik.com Git - wxWidgets.git/commitdiff
Forward port of my recent changes in the 2.8 branch:
authorRobin Dunn <robin@alldunn.com>
Mon, 26 Mar 2007 20:08:41 +0000 (20:08 +0000)
committerRobin Dunn <robin@alldunn.com>
Mon, 26 Mar 2007 20:08:41 +0000 (20:08 +0000)
 * Force use of floating point math in wxGCDC::DoDrawEllipticArc.

 * Check for 0.5 offset in wxGCDC::DoDrawRoundedRectangle and
   DoDrawEllipse.  Set wxGDIPlusContext to use the offset.

 * Avoid crash in wxStdDialogButtonSizer::Realize if there is no
   negative button.

 * Provide implementations for wxCairoPathData::AddPath,
   wxCairoContext::Clip, wxCairoContext::DrawBitmap,
   wxCairoContext::DrawIcon, and wxCairoContext::GetTextExtent.

 * Fix wxCairoContext::DrawText to draw the text using the upper-left
   corner for the x,y position, not the baseline.

 * Fix wxMacCoreGraphicsRenderer::CreateContext to be able to use a
   wxMemoryDC as the target.

 * Map wxTELETYPE font family on wxMac to a monospace font.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45077 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/common/dcgraph.cpp
src/common/sizer.cpp
src/generic/graphicc.cpp
src/mac/carbon/font.cpp
src/mac/carbon/graphics.cpp
src/msw/graphics.cpp

index 40ff9d38d9d01d530ea55a2aa388d4187a568411..93ee03514dec315a14fadaf04249fd1ddad0d3ff 100644 (file)
@@ -501,20 +501,15 @@ void wxGCDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
     if ( !m_logicalFunctionSupported )
         return;
 
-    bool fill = m_brush.GetStyle() != wxTRANSPARENT;
-
     wxGraphicsPath path = m_graphicContext->CreatePath();
     m_graphicContext->PushState();
-    m_graphicContext->Translate(x+w/2,y+h/2);
+    m_graphicContext->Translate(x+w/2.0,y+h/2.0);
     wxDouble factor = ((wxDouble) w) / h;
     m_graphicContext->Scale( factor , 1.0);
-    if ( fill && (sa!=ea) )
-        path.MoveToPoint(0,0);
+
     // since these angles (ea,sa) are measured counter-clockwise, we invert them to
     // get clockwise angles
-    path.AddArc( 0, 0, h/2 , DegToRad(-sa) , DegToRad(-ea), sa > ea );
-    if ( fill && (sa!=ea) )
-        path.AddLineToPoint(0,0);
+    path.AddArc( 0, 0, h/2.0 , DegToRad(-sa) , DegToRad(-ea), sa > ea );
     m_graphicContext->DrawPath( path );
     m_graphicContext->PopState();
 }
@@ -698,6 +693,13 @@ void wxGCDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
     if (w == 0 || h == 0)
         return;
 
+    if ( m_graphicContext->ShouldOffset() )
+    {
+        // if we are offsetting the entire rectangle is moved 0.5, so the
+        // border line gets off by 1
+        w -= 1;
+        h -= 1;
+    }
     m_graphicContext->DrawRoundedRectangle( x,y,w,h,radius);
 }
 
@@ -708,6 +710,13 @@ void wxGCDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
     if ( !m_logicalFunctionSupported )
         return;
 
+    if ( m_graphicContext->ShouldOffset() )
+    {
+        // if we are offsetting the entire rectangle is moved 0.5, so the
+        // border line gets off by 1
+        w -= 1;
+        h -= 1;
+    }
     m_graphicContext->DrawEllipse(x,y,w,h);
 }
 
index 0fc04d7c37e71ff850b2cf5d636a6071237cd953..66a15254319762ba59fa1d35d1abc88041db13be 100644 (file)
@@ -2022,7 +2022,8 @@ void wxStdDialogButtonSizer::Realize()
             if (m_buttonAffirmative->GetId() == wxID_SAVE){
                 // these buttons have set labels under Mac so we should use them
                 m_buttonAffirmative->SetLabel(_("Save"));
-                m_buttonNegative->SetLabel(_("Don't Save"));
+                if (m_buttonNegative)
+                    m_buttonNegative->SetLabel(_("Don't Save"));
             }
         }
 
index 7ab1b5cdaf029e3d0b3a57c29702943c18e78f80..f40b1c58451d7da7805bfb198930fcb895703dbe 100755 (executable)
@@ -37,6 +37,7 @@
 #endif
 
 #include "wx/graphics.h"
+#include "wx/rawbmp.h"
 
 #if wxUSE_GRAPHICS_CONTEXT
 
@@ -757,7 +758,9 @@ void wxCairoPathData::AddLineToPoint( wxDouble x , wxDouble y )
 
 void wxCairoPathData::AddPath( const wxGraphicsPathData* path )
 {
-    // TODO
+    cairo_path_t* p = (cairo_path_t*)path->GetNativePath();
+    cairo_append_path(m_pathContext, p);
+    UnGetNativePath(p);
 }
 
 void wxCairoPathData::CloseSubpath()
@@ -1028,19 +1031,44 @@ wxCairoContext::~wxCairoContext()
 }
 
 
-void wxCairoContext::Clip( const wxRegion & WXUNUSED(region) )
+void wxCairoContext::Clip( const wxRegion& region )
 {
-// TODO
+    // Create a path with all the rectangles in the region
+    wxGraphicsPath path = GetRenderer()->CreatePath();
+    wxRegionIterator ri(region);
+    while (ri)
+    {
+        path.AddRectangle(ri.GetX(), ri.GetY(), ri.GetW(), ri.GetH());
+        ri++;
+    }
+    
+    // Put it in the context
+    cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ;
+    cairo_append_path(m_context, cp);
+
+    // clip to that path
+    cairo_clip(m_context);
+    path.UnGetNativePath(cp);  
 }
 
 void wxCairoContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
-// TODO
+    // Create a path with this rectangle
+    wxGraphicsPath path = GetRenderer()->CreatePath();
+    path.AddRectangle(x,y,w,h);
+
+    // Put it in the context
+    cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ;
+    cairo_append_path(m_context, cp);
+
+    // clip to that path
+    cairo_clip(m_context);
+    path.UnGetNativePath(cp);  
 }
 
 void wxCairoContext::ResetClip()
 {
-// TODO
+    cairo_reset_clip(m_context);
 }
 
 
@@ -1118,37 +1146,156 @@ void wxCairoContext::PopState()
 
 void wxCairoContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
-    /*
-        Bitmap* image = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE());
-        m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ;
-        delete image ;
-    */
+    wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap"));
+
+    cairo_surface_t* surface;
+    int bw = bmp.GetWidth();
+    int bh = bmp.GetHeight();
+    wxBitmap bmpSource = bmp;  // we need a non-const instance
+    unsigned char* buffer = new unsigned char[bw*bh*4];
+    wxUint32* data = (wxUint32*)buffer;
+    
+    // Create a surface object and copy the bitmap pixel data to it.  if the
+    // image has alpha (or a mask represented as alpha) then we'll use a
+    // different format and iterator than if it doesn't...
+    if (bmpSource.HasAlpha() || bmpSource.GetMask())
+    {
+        surface = cairo_image_surface_create_for_data(
+            buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4);
+        wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
+        wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
+        
+        wxAlphaPixelData::Iterator p(pixData);
+        for (int y=0; y<bh; y++)
+        {
+            wxAlphaPixelData::Iterator rowStart = p;
+            for (int x=0; x<bw; x++)
+            {
+                // Each pixel in CAIRO_FORMAT_ARGB32 is a 32-bit quantity,
+                // with alpha in the upper 8 bits, then red, then green, then
+                // blue. The 32-bit quantities are stored native-endian.
+                // Pre-multiplied alpha is used.
+                unsigned char alpha = p.Alpha();
+                if (alpha == 0)
+                    *data = 0;
+                else
+                    *data = ( alpha                      << 24 
+                              | (p.Red() * alpha/255)    << 16 
+                              | (p.Green() * alpha/255)  <<  8 
+                              | (p.Blue() * alpha/255) );
+                ++data;
+                ++p;
+            }
+            p = rowStart;
+            p.OffsetY(pixData, 1);
+        }        
+    }
+    else  // no alpha
+    {
+        surface = cairo_image_surface_create_for_data(
+            buffer, CAIRO_FORMAT_RGB24, bw, bh, bw*4);
+        wxNativePixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
+        wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
+        
+        wxNativePixelData::Iterator p(pixData);
+        for (int y=0; y<bh; y++)
+        {
+            wxNativePixelData::Iterator rowStart = p;
+            for (int x=0; x<bw; x++)
+            {
+                // Each pixel in CAIRO_FORMAT_RGB24 is a 32-bit quantity, with
+                // the upper 8 bits unused. Red, Green, and Blue are stored in
+                // the remaining 24 bits in that order.  The 32-bit quantities
+                // are stored native-endian.
+                *data = ( p.Red() << 16 | p.Green() << 8 | p.Blue() );
+                ++data;
+                ++p;
+            }
+            p = rowStart;
+            p.OffsetY(pixData, 1);
+        }        
+    }
+
+    
+    PushState();
+    
+    // In case we're scaling the image by using a width and height different
+    // than the bitmap's size create a pattern transformation on the surface and
+    // draw the transformed pattern.
+    cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
+    wxDouble scaleX = w / bw;
+    wxDouble scaleY = h / bh;
+    cairo_scale(m_context, scaleX, scaleY);
+
+    // prepare to draw the image
+    cairo_translate(m_context, x, y);
+    cairo_set_source(m_context, pattern);
+    // use the original size here since the context is scaled already...
+    cairo_rectangle(m_context, 0, 0, bw, bh);
+    // fill the rectangle using the pattern
+    cairo_fill(m_context);
+
+    // clean up
+    cairo_pattern_destroy(pattern);
+    cairo_surface_destroy(surface);
+    delete [] buffer;
+    PopState();
 }
 
 void wxCairoContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
-    /*
-        Bitmap* image = Bitmap::FromHICON((HICON)icon.GetHICON());
-        m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ;
-        delete image ;
-    */
+    // An icon is a bitmap on wxGTK, so do this the easy way.  When we want to
+    // start using the Cairo backend on other platforms then we may need to
+    // fiddle with this...
+    DrawBitmap(icon, x, y, w, h);
 }
 
 
 void wxCairoContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
 {
-    if ( m_font.IsNull() || str.IsEmpty())
-        return ;
-    cairo_move_to(m_context,x,y);
-    const wxWX2MBbuf buf(str.mb_str(wxConvUTF8));
+    if ( m_font.IsNull() || str.empty())
+        return;
+    
     ((wxCairoFontData*)m_font.GetRefData())->Apply(this);
+
+    // Cairo's x,y for drawing text is at the baseline, so we need to adjust
+    // the position we move to by the ascent.
+    cairo_font_extents_t fe;
+    cairo_font_extents(m_context, &fe);
+    cairo_move_to(m_context, x, y+fe.ascent);
+    
+    const wxWX2MBbuf buf(str.mb_str(wxConvUTF8));
     cairo_show_text(m_context,buf);
 }
 
 void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
                                     wxDouble *descent, wxDouble *externalLeading ) const
 {
-    // TODO
+    if ( m_font.IsNull() || str.empty())
+        return;
+
+    ((wxCairoFontData*)m_font.GetRefData())->Apply((wxCairoContext*)this);
+
+    if (width)
+    {
+        const wxWX2MBbuf buf(str.mb_str(wxConvUTF8));
+        cairo_text_extents_t te;
+        cairo_text_extents(m_context, buf, &te);
+        *width = te.width;
+    }
+
+    if (height || descent || externalLeading)
+    {
+        cairo_font_extents_t fe;
+        cairo_font_extents(m_context, &fe);
+    
+        if (height)
+            *height = fe.height;
+        if ( descent )
+            *descent = fe.descent;
+        if ( externalLeading )
+            *externalLeading = wxMax(0, fe.height - (fe.ascent + fe.descent));
+    }
 }
 
 void wxCairoContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
index 77a08d785554528eb563b5c06c8d2ca9edd28d6f..fe8a315e25a9ad7d58437cda7cf616f235a9d13c 100644 (file)
@@ -254,6 +254,7 @@ void wxFontRefData::MacFindFont()
                         break ;
 
                     case wxMODERN :
+                    case wxTELETYPE:
                         m_faceName =  wxT("Monaco");
                         break ;
 
index 0a226352027732ba66748fa6b8a67b6b653e6969..b2bcb0788a9431e197ce8454feae9de93cc4c35e 100755 (executable)
@@ -17,6 +17,7 @@
 
 #ifndef WX_PRECOMP
     #include "wx/dcclient.h"
+    #include "wx/dcmemory.h"
     #include "wx/log.h"
     #include "wx/region.h"
 #endif
@@ -2013,7 +2014,16 @@ wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
 
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc)
 {
-   return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
+    wxMemoryDC* mdc = wxDynamicCast(&dc, wxMemoryDC);
+    if ( mdc )
+    {
+        return new wxMacCoreGraphicsContext(this, 
+            (CGContextRef)mdc->GetGraphicsContext()->GetNativeContext());
+    }
+    else
+    {
+        return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
+    }
 }
 
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )
index 142c2f60e854e16827ad1818750673d12654883e..bda43979a70c9a988ce2a67aa3fb38c376a42693 100644 (file)
@@ -303,6 +303,7 @@ public:
     virtual void GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
         wxDouble *descent, wxDouble *externalLeading ) const;
     virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
+    virtual bool ShouldOffset() const;
 
 private:
     void    Init();
@@ -1185,6 +1186,18 @@ void wxGDIPlusContext::GetPartialTextExtents(const wxString& text, wxArrayDouble
     }
 }
 
+bool wxGDIPlusContext::ShouldOffset() const
+{     
+    int penwidth = 0 ;
+    if ( !m_pen.IsNull() )
+    {
+        penwidth = (int)((wxGDIPlusPenData*)m_pen.GetRefData())->GetWidth();
+        if ( penwidth == 0 )
+            penwidth = 1;
+    }
+    return ( penwidth % 2 ) == 1;
+}
+
 void* wxGDIPlusContext::GetNativeContext()
 {
     return m_context;