]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/graphicc.cpp
use wxWANTS_CHARS to allow arrows to work inside the control
[wxWidgets.git] / src / generic / graphicc.cpp
index ab7178ce8c5382eb897af53357510ca3e2cad6b2..b70fbd4f9a4c4727d4621c22bc7f8ce8da0888a8 100644 (file)
 
 #include "wx/wxprec.h"
 
-#include "wx/dc.h"
-
 #ifdef __BORLANDC__
 #pragma hdrstop
 #endif
 
+#if wxUSE_GRAPHICS_CONTEXT
+
+#include "wx/dc.h"
+
 #ifndef WX_PRECOMP
 #include "wx/image.h"
 #include "wx/window.h"
 #include "wx/module.h"
 #endif
 
-#ifdef __WXGTK__
-#include <gtk/gtk.h>
-#endif
-
-#include "wx/graphics.h"
+#include "wx/private/graphics.h"
 #include "wx/rawbmp.h"
 
-#if wxUSE_GRAPHICS_CONTEXT
-
 #include <vector>
 
 using namespace std;
@@ -101,8 +97,9 @@ static inline double RadToDeg(double deg)
 
 #include <cairo.h>
 #ifdef __WXGTK__
-#include "wx/gtk/win_gtk.h"
 #include <gtk/gtk.h>
+#include "wx/fontutil.h"
+#include "wx/gtk/dc.h"
 #endif
 
 #ifdef __WXMSW__
@@ -301,17 +298,24 @@ public:
     ~wxCairoFontData();
 
     virtual void Apply( wxGraphicsContext* context );
+#ifdef __WXGTK__
+    const PangoFontDescription* GetFont() const { return m_font; }
+#endif
 private :
-    wxCharBuffer m_fontName;
     double m_size;
-    cairo_font_slant_t m_slant;
-    cairo_font_weight_t m_weight;
     double m_red;
     double m_green;
     double m_blue;
     double m_alpha;
+#ifdef __WXMAC__
     cairo_font_face_t *m_font;
-    wxFont m_wxFont;
+#elif defined(__WXGTK__)
+    PangoFontDescription* m_font;
+#else
+    wxCharBuffer m_fontName;
+    cairo_font_slant_t m_slant;
+    cairo_font_weight_t m_weight;
+#endif
 };
 
 class WXDLLIMPEXP_CORE wxCairoContext : public wxGraphicsContext
@@ -320,6 +324,7 @@ class WXDLLIMPEXP_CORE wxCairoContext : public wxGraphicsContext
 
 public:
     wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC& dc );
+    wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& dc );
 #ifdef __WXGTK__
     wxCairoContext( wxGraphicsRenderer* renderer, GdkDrawable *drawable );
 #endif
@@ -482,17 +487,17 @@ wxCairoPenData::wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen )
         break;
 
     case wxLONG_DASH :
-        m_lengths = dotted ;
+        m_lengths = dashed ;
         m_count = WXSIZEOF(dashed);
         break;
 
     case wxSHORT_DASH :
-        m_lengths = dotted ;
+        m_lengths = short_dashed ;
         m_count = WXSIZEOF(short_dashed);
         break;
 
     case wxDOT_DASH :
-        m_lengths = dotted ;
+        m_lengths = dotted_dashed ;
         m_count = WXSIZEOF(dotted_dashed);
         break;
 
@@ -701,38 +706,41 @@ wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &fo
     m_green = col.Green()/255.0; 
     m_blue = col.Blue()/255.0;
     m_alpha = col.Alpha()/255.0;
-
     m_size = font.GetPointSize();
+
+#ifdef __WXMAC__
+    m_font = cairo_atsui_font_face_create_for_atsu_font_id( font.MacGetATSUFontID() );
+#elif defined(__WXGTK__)
+    m_font = pango_font_description_copy( font.GetNativeFontInfo()->description );
+#else
     m_fontName = font.GetFaceName().mb_str(wxConvUTF8);
     m_slant = font.GetStyle() == wxFONTSTYLE_ITALIC ? CAIRO_FONT_SLANT_ITALIC:CAIRO_FONT_SLANT_NORMAL;
     m_weight = font.GetWeight() == wxFONTWEIGHT_BOLD ? CAIRO_FONT_WEIGHT_BOLD:CAIRO_FONT_WEIGHT_NORMAL;
-#ifdef __WXMAC__
-    m_font = cairo_atsui_font_face_create_for_atsu_font_id( font.MacGetATSUFontID() );
-#endif
-#ifdef __WXMSW__
-#endif
-#ifdef __WXGTK__
-    // Pango implementation uses the native descriptor
-    m_font = NULL;
-    m_wxFont = font;
 #endif
 }
 
 wxCairoFontData::~wxCairoFontData()
 {
+#ifdef __WXMAC__
     cairo_font_face_destroy( m_font );
+#elif defined(__WXGTK__)
+    pango_font_description_free( m_font );
+#else
+#endif
 }
 
 void wxCairoFontData::Apply( wxGraphicsContext* context )
 {
-#ifdef __WXGTK__
-    // Pango handled differently
-#else
     cairo_t * ctext = (cairo_t*) context->GetNativeContext();
     cairo_set_source_rgba(ctext,m_red,m_green, m_blue,m_alpha);
-    cairo_set_font_face(ctext, m_font );
-    // TODO UNDERLINE
-    // TODO FIX SIZE
+#ifdef __WXGTK__
+    // the rest is done using Pango layouts
+#elif defined(__WXMAC__)
+    cairo_set_font_face(ctext, m_font);
+    cairo_set_font_size(ctext, m_size );
+#else
+    cairo_select_font_face(ctext, m_fontName, m_slant, m_weights );
+    cairo_set_font_size(ctext, m_size );
 #endif
 }
 
@@ -875,7 +883,7 @@ void wxCairoPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h)
     }
 }
 
-bool wxCairoPathData::Contains( wxDouble x, wxDouble y, int fillStyle ) const
+bool wxCairoPathData::Contains( wxDouble x, wxDouble y, int WXUNUSED(fillStyle) ) const
 {
     return cairo_in_stroke( m_pathContext, x, y) != 0;
 }
@@ -1030,7 +1038,25 @@ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC&
 : wxGraphicsContext(renderer)
 {
 #ifdef __WXGTK__
-    Init( gdk_cairo_create( dc.m_window ) );
+    wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
+    Init( gdk_cairo_create( impldc->GetGDKWindow() ) );
+#endif
+#ifdef __WXMAC__
+    int width, height;
+    dc.GetSize( &width, &height );
+    CGContextRef cgcontext = (CGContextRef)dc.GetWindow()->MacGetCGContextRef();
+    cairo_surface_t* surface = cairo_quartz_surface_create_for_cg_context(cgcontext, width, height);
+    Init( cairo_create( surface ) );
+    cairo_surface_destroy( surface );
+#endif
+}
+
+wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& dc )
+: wxGraphicsContext(renderer)
+{
+#ifdef __WXGTK__
+    wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
+    Init( gdk_cairo_create( impldc->GetGDKWindow() ) );
 #endif
 #ifdef __WXMAC__
     int width, height;
@@ -1062,22 +1088,17 @@ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, wxWindow *window)
 #ifdef __WXGTK__
     // something along these lines (copied from dcclient)
 
-    GtkWidget *widget = window->m_wxwindow;
-
     // Some controls don't have m_wxwindow - like wxStaticBox, but the user
     // code should still be able to create wxClientDCs for them, so we will
     // use the parent window here then.
-    if ( !widget )
+    if (window->m_wxwindow == NULL)
     {
         window = window->GetParent();
-        widget = window->m_wxwindow;
     }
 
-    wxASSERT_MSG( widget, wxT("wxCairoContext needs a widget") );
+    wxASSERT_MSG( window->m_wxwindow, wxT("wxCairoContext needs a widget") );
 
-    GtkPizza *pizza = GTK_PIZZA( widget );
-    GdkDrawable* drawable = pizza->bin_window;
-    Init( gdk_cairo_create( drawable ) ) ;
+    Init(gdk_cairo_create(window->GTKGetDrawingWindow()));
 #endif
 }
 
@@ -1107,7 +1128,7 @@ void wxCairoContext::Clip( const wxRegion& region )
     while (ri)
     {
         path.AddRectangle(ri.GetX(), ri.GetY(), ri.GetW(), ri.GetH());
-        ri++;
+        ++ri;
     }
     
     // Put it in the context
@@ -1130,7 +1151,7 @@ void wxCairoContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
     cairo_append_path(m_context, cp);
 
     // clip to that path
-//    cairo_clip(m_context);
+    cairo_clip(m_context);
     path.UnGetNativePath(cp);  
 }
 
@@ -1325,16 +1346,17 @@ void wxCairoContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
 {
     if ( m_font.IsNull() || str.empty())
         return;
-    
+
 #ifdef __WXGTK__
-    const wxCharBuffer data = wxGTK_CONV( str );
+    const wxCharBuffer data = str.utf8_str();
     if ( !data )
         return;
     size_t datalen = strlen(data);
-  
+    ((wxCairoFontData*)m_font.GetRefData())->Apply(this);
+
     PangoLayout *layout = pango_cairo_create_layout (m_context);
-    pango_layout_set_font_description( m_layout, m_wxFont->GetNativeFontInfo()->description);
-    pango_layout_set_text (layout, data, datalen);
+    pango_layout_set_font_description( layout, ((wxCairoFontData*)m_font.GetRefData())->GetFont());
+    pango_layout_set_text(layout, data, datalen);
     cairo_move_to(m_context, x, y);
     pango_cairo_show_layout (m_context, layout);
 
@@ -1371,13 +1393,13 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub
     int w, h;
   
     PangoLayout *layout = pango_cairo_create_layout (m_context);
-    pango_layout_set_font_description( layout, m_wxFont->GetNativeFontInfo()->description);
-    const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(str, m_wxFont);
-    if ( !dataUTF8 )
+    pango_layout_set_font_description( layout, ((wxCairoFontData*)m_font.GetRefData())->GetFont());
+    const wxCharBuffer data = str.utf8_str();
+    if ( !data )
     {
         return;
     }
-    pango_layout_set_text( layout, dataUTF8, strlen(dataUTF8) );
+    pango_layout_set_text( layout, data, strlen(data) );
     pango_layout_get_pixel_size (layout, &w, &h);
     if ( width )
         *width = w;
@@ -1406,6 +1428,17 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub
     {
         cairo_font_extents_t fe;
         cairo_font_extents(m_context, &fe);
+        
+        // some backends have negative descents
+        
+        if ( fe.descent < 0 )
+            fe.descent = -fe.descent;
+    
+        if ( fe.height < (fe.ascent + fe.descent ) )
+        {
+            // some backends are broken re height ... (eg currently ATSUI)
+            fe.height = fe.ascent + fe.descent;
+        }
     
         if (height)
             *height = fe.height;
@@ -1447,10 +1480,7 @@ public :
     // Context
 
     virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
-
-#ifdef __WXMSW__
     virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc);
-#endif
 
     virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
 
@@ -1497,6 +1527,9 @@ private :
 IMPLEMENT_DYNAMIC_CLASS(wxCairoRenderer,wxGraphicsRenderer)
 
 static wxCairoRenderer gs_cairoGraphicsRenderer;
+// temporary hack to allow creating a cairo context on any platform
+extern wxGraphicsRenderer* gCairoRenderer;
+wxGraphicsRenderer* gCairoRenderer = &gs_cairoGraphicsRenderer;
 
 #ifdef __WXGTK__
 wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
@@ -1510,12 +1543,10 @@ wxGraphicsContext * wxCairoRenderer::CreateContext( const wxWindowDC& dc)
     return new wxCairoContext(this,dc);
 }
 
-#ifdef __WXMSW__
 wxGraphicsContext * wxCairoRenderer::CreateContext( const wxMemoryDC& dc)
 {
-    return NULL;
+    return new wxCairoContext(this,dc);
 }
-#endif
 
 wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeContext( void * context )
 {